Compare commits
5 Commits
v0.17.3
...
derive-doc
Author | SHA1 | Date | |
---|---|---|---|
f5ee346408 | |||
544a7565e3 | |||
979046f7e6 | |||
07ae5106b9 | |||
e9ae484332 |
@ -1,3 +1,3 @@
|
|||||||
[codespell]
|
[codespell]
|
||||||
ignore-words-list: crate,everytime,inout,co-ordinate,ot,nwo,absolutey,atleast
|
ignore-words-list: crate,everytime,inout,co-ordinate,ot,nwo,absolutey,atleast
|
||||||
skip: **/target,node_modules,build,**/Cargo.lock,./docs/kcl/*.md
|
skip: **/target,node_modules,build,**/Cargo.lock,./docs/kcl/*.md,./src-tauri/gen/schemas
|
||||||
|
26
.github/workflows/ci.yml
vendored
@ -125,6 +125,9 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
os: [macos-14, ubuntu-latest, windows-latest]
|
os: [macos-14, ubuntu-latest, windows-latest]
|
||||||
|
env:
|
||||||
|
TAURI_ARGS_MACOS: ${{ matrix.os == 'macos-14' && '--target universal-apple-darwin' || '' }}
|
||||||
|
TAURI_ARGS_UBUNTU: ${{ matrix.os == 'ubuntu-latest' && '--bundles' || '' }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
@ -144,10 +147,12 @@ jobs:
|
|||||||
sudo apt-get update &&
|
sudo apt-get update &&
|
||||||
sudo apt-get install -y
|
sudo apt-get install -y
|
||||||
libgtk-3-dev
|
libgtk-3-dev
|
||||||
libgtksourceview-3.0-dev
|
libayatana-appindicator3-dev
|
||||||
webkit2gtk-4.0
|
|
||||||
libappindicator3-dev
|
|
||||||
webkit2gtk-driver
|
webkit2gtk-driver
|
||||||
|
libsoup-3.0-dev
|
||||||
|
libjavascriptcoregtk-4.1-dev
|
||||||
|
libwebkit2gtk-4.1-dev
|
||||||
|
at-spi2-core
|
||||||
xvfb
|
xvfb
|
||||||
|
|
||||||
- name: Sync node version and setup cache
|
- name: Sync node version and setup cache
|
||||||
@ -161,7 +166,9 @@ jobs:
|
|||||||
- name: Setup Rust
|
- name: Setup Rust
|
||||||
uses: dtolnay/rust-toolchain@stable
|
uses: dtolnay/rust-toolchain@stable
|
||||||
|
|
||||||
|
# TODO: re-enable for Windows builds, see https://github.com/tauri-apps/tauri/issues/9045
|
||||||
- name: Setup Rust cache
|
- name: Setup Rust cache
|
||||||
|
if: matrix.os != 'windows-latest'
|
||||||
uses: swatinem/rust-cache@v2
|
uses: swatinem/rust-cache@v2
|
||||||
with:
|
with:
|
||||||
workspaces: './src-tauri -> target'
|
workspaces: './src-tauri -> target'
|
||||||
@ -224,14 +231,14 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
includeRelease: false
|
includeRelease: false
|
||||||
includeDebug: true
|
includeDebug: true
|
||||||
args: ${{ matrix.os == 'macos-14' && '--target universal-apple-darwin' || '' }}
|
args: "${{ env.TAURI_ARGS_MACOS }} ${{ env.TAURI_ARGS_UBUNTU }}"
|
||||||
|
|
||||||
- name: Build the app (release) and sign
|
- name: Build the app (release) and sign
|
||||||
uses: tauri-apps/tauri-action@v0
|
uses: tauri-apps/tauri-action@v0
|
||||||
if: ${{ env.BUILD_RELEASE == 'true' }}
|
if: ${{ env.BUILD_RELEASE == 'true' }}
|
||||||
env:
|
env:
|
||||||
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
|
||||||
TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
|
||||||
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
|
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
|
||||||
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
|
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
|
||||||
APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }}
|
APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }}
|
||||||
@ -240,7 +247,7 @@ jobs:
|
|||||||
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
||||||
TAURI_CONF_ARGS: "--config ${{ matrix.os == 'windows-latest' && 'src-tauri\\tauri.release.conf.json' || 'src-tauri/tauri.release.conf.json' }}"
|
TAURI_CONF_ARGS: "--config ${{ matrix.os == 'windows-latest' && 'src-tauri\\tauri.release.conf.json' || 'src-tauri/tauri.release.conf.json' }}"
|
||||||
with:
|
with:
|
||||||
args: "${{ matrix.os == 'macos-14' && '--target universal-apple-darwin' || '' }} ${{ env.TAURI_CONF_ARGS }}"
|
args: "${{ env.TAURI_CONF_ARGS }} ${{ env.TAURI_ARGS_MACOS }} ${{ env.TAURI_ARGS_UBUNTU }}"
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v3
|
- uses: actions/upload-artifact@v3
|
||||||
if: matrix.os != 'ubuntu-latest'
|
if: matrix.os != 'ubuntu-latest'
|
||||||
@ -250,10 +257,11 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
path: "${{ env.PREFIX }}/${{ env.MODE }}/bundle/*/*"
|
path: "${{ env.PREFIX }}/${{ env.MODE }}/bundle/*/*"
|
||||||
|
|
||||||
|
# TODO: re-enable linux e2e tests when possible
|
||||||
- name: Run e2e tests (linux only)
|
- name: Run e2e tests (linux only)
|
||||||
if: matrix.os == 'ubuntu-latest'
|
if: false
|
||||||
run: |
|
run: |
|
||||||
cargo install tauri-driver@0.1.3
|
cargo install tauri-driver
|
||||||
source .env.${{ env.BUILD_RELEASE == 'true' && 'production' || 'development' }}
|
source .env.${{ env.BUILD_RELEASE == 'true' && 'production' || 'development' }}
|
||||||
export VITE_KC_API_BASE_URL
|
export VITE_KC_API_BASE_URL
|
||||||
xvfb-run yarn test:e2e:tauri
|
xvfb-run yarn test:e2e:tauri
|
||||||
|
1
.gitignore
vendored
@ -51,5 +51,6 @@ e2e/playwright/export-snapshots/*
|
|||||||
|
|
||||||
## generated files
|
## generated files
|
||||||
src/**/*.typegen.ts
|
src/**/*.typegen.ts
|
||||||
|
src-tauri/gen
|
||||||
|
|
||||||
src/wasm-lib/grackle/stdlib_cube_partial.json
|
src/wasm-lib/grackle/stdlib_cube_partial.json
|
||||||
|
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 47 KiB |
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 50 KiB |
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 48 KiB |
12
package.json
@ -16,7 +16,12 @@
|
|||||||
"@open-rpc/client-js": "^1.8.1",
|
"@open-rpc/client-js": "^1.8.1",
|
||||||
"@react-hook/resize-observer": "^1.2.6",
|
"@react-hook/resize-observer": "^1.2.6",
|
||||||
"@replit/codemirror-interact": "^6.3.0",
|
"@replit/codemirror-interact": "^6.3.0",
|
||||||
"@tauri-apps/api": "^1.5.3",
|
"@tauri-apps/api": "^2.0.0-beta.7",
|
||||||
|
"@tauri-apps/plugin-dialog": "^2.0.0-beta.2",
|
||||||
|
"@tauri-apps/plugin-fs": "^2.0.0-beta.2",
|
||||||
|
"@tauri-apps/plugin-http": "^2.0.0-beta.2",
|
||||||
|
"@tauri-apps/plugin-os": "^2.0.0-beta.2",
|
||||||
|
"@tauri-apps/plugin-shell": "^2.0.0-beta.2",
|
||||||
"@testing-library/jest-dom": "^5.14.1",
|
"@testing-library/jest-dom": "^5.14.1",
|
||||||
"@testing-library/react": "^14.0.0",
|
"@testing-library/react": "^14.0.0",
|
||||||
"@testing-library/user-event": "^14.5.2",
|
"@testing-library/user-event": "^14.5.2",
|
||||||
@ -48,7 +53,6 @@
|
|||||||
"react-router-dom": "^6.22.3",
|
"react-router-dom": "^6.22.3",
|
||||||
"sketch-helpers": "^0.0.4",
|
"sketch-helpers": "^0.0.4",
|
||||||
"swr": "^2.2.2",
|
"swr": "^2.2.2",
|
||||||
"tauri-plugin-fs-extra-api": "https://github.com/tauri-apps/tauri-plugin-fs-extra#v1",
|
|
||||||
"three": "^0.160.0",
|
"three": "^0.160.0",
|
||||||
"toml": "^3.0.0",
|
"toml": "^3.0.0",
|
||||||
"ts-node": "^10.9.2",
|
"ts-node": "^10.9.2",
|
||||||
@ -86,7 +90,7 @@
|
|||||||
"remove-importmeta": "sed -i 's/import.meta.url/window.location.origin/g' \"./src/wasm-lib/pkg/wasm_lib.js\"; sed -i '' 's/import.meta.url/window.location.origin/g' \"./src/wasm-lib/pkg/wasm_lib.js\" || echo \"sed for both mac and linux\"",
|
"remove-importmeta": "sed -i 's/import.meta.url/window.location.origin/g' \"./src/wasm-lib/pkg/wasm_lib.js\"; sed -i '' 's/import.meta.url/window.location.origin/g' \"./src/wasm-lib/pkg/wasm_lib.js\" || echo \"sed for both mac and linux\"",
|
||||||
"wasm-prep": "rm -rf src/wasm-lib/pkg && mkdir src/wasm-lib/pkg && rm -rf src/wasm-lib/kcl/bindings",
|
"wasm-prep": "rm -rf src/wasm-lib/pkg && mkdir src/wasm-lib/pkg && rm -rf src/wasm-lib/kcl/bindings",
|
||||||
"lint": "eslint --fix src",
|
"lint": "eslint --fix src",
|
||||||
"bump-jsons": "echo \"$(jq --arg v \"$VERSION\" '.version=$v' package.json --indent 2)\" > package.json && echo \"$(jq --arg v \"$VERSION\" '.package.version=$v' src-tauri/tauri.conf.json --indent 2)\" > src-tauri/tauri.conf.json",
|
"bump-jsons": "echo \"$(jq --arg v \"$VERSION\" '.version=$v' package.json --indent 2)\" > package.json && echo \"$(jq --arg v \"$VERSION\" '.version=$v' src-tauri/tauri.conf.json --indent 2)\" > src-tauri/tauri.conf.json",
|
||||||
"postinstall": "yarn xstate:typegen",
|
"postinstall": "yarn xstate:typegen",
|
||||||
"xstate:typegen": "yarn xstate typegen \"src/**/*.ts?(x)\""
|
"xstate:typegen": "yarn xstate typegen \"src/**/*.ts?(x)\""
|
||||||
},
|
},
|
||||||
@ -112,7 +116,7 @@
|
|||||||
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
|
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
|
||||||
"@babel/preset-env": "^7.24.3",
|
"@babel/preset-env": "^7.24.3",
|
||||||
"@playwright/test": "^1.39.0",
|
"@playwright/test": "^1.39.0",
|
||||||
"@tauri-apps/cli": "^1.5.11",
|
"@tauri-apps/cli": "^2.0.0-beta.12",
|
||||||
"@types/crypto-js": "^4.2.2",
|
"@types/crypto-js": "^4.2.2",
|
||||||
"@types/debounce-promise": "^3.1.9",
|
"@types/debounce-promise": "^3.1.9",
|
||||||
"@types/pixelmatch": "^5.2.6",
|
"@types/pixelmatch": "^5.2.6",
|
||||||
|
2545
src-tauri/Cargo.lock
generated
@ -7,12 +7,12 @@ license = ""
|
|||||||
repository = "https://github.com/KittyCAD/modeling-app"
|
repository = "https://github.com/KittyCAD/modeling-app"
|
||||||
default-run = "app"
|
default-run = "app"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
rust-version = "1.60"
|
rust-version = "1.70"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
tauri-build = { version = "1.5.1", features = [] }
|
tauri-build = { version = "2.0.0-beta", features = [] }
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1"
|
anyhow = "1"
|
||||||
@ -20,8 +20,13 @@ kittycad = "0.2.63"
|
|||||||
oauth2 = "4.4.2"
|
oauth2 = "4.4.2"
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
tauri = { version = "1.6.1", features = [ "os-all", "dialog-all", "fs-all", "http-request", "path-all", "shell-open", "shell-open-api", "devtools"] }
|
tauri = { version = "2.0.0-beta", features = [ "devtools", "unstable"] }
|
||||||
tauri-plugin-fs-extra = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" }
|
tauri-plugin-dialog = { version = "2.0.0-beta.0" }
|
||||||
|
tauri-plugin-fs = { version = "2.0.0-beta.0" }
|
||||||
|
tauri-plugin-http = { version = "2.0.0-beta.0" }
|
||||||
|
tauri-plugin-os = { version = "2.0.0-beta.0" }
|
||||||
|
tauri-plugin-shell = { version = "2.0.0-beta.0" }
|
||||||
|
tauri-plugin-updater = { version = "2.0.0-beta.0" }
|
||||||
tokio = { version = "1.37.0", features = ["time"] }
|
tokio = { version = "1.37.0", features = ["time"] }
|
||||||
toml = "0.8.2"
|
toml = "0.8.2"
|
||||||
|
|
||||||
|
87
src-tauri/capabilities/desktop.json
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
{
|
||||||
|
"$schema": "../gen/schemas/desktop-schema.json",
|
||||||
|
"identifier": "main-capability",
|
||||||
|
"description": "Capability for the main window",
|
||||||
|
"context": "local",
|
||||||
|
"windows": [
|
||||||
|
"main"
|
||||||
|
],
|
||||||
|
"permissions": [
|
||||||
|
"path:default",
|
||||||
|
"event:default",
|
||||||
|
"window:default",
|
||||||
|
"app:default",
|
||||||
|
"resources:default",
|
||||||
|
"menu:default",
|
||||||
|
"tray:default",
|
||||||
|
"fs:allow-create",
|
||||||
|
"fs:allow-read-file",
|
||||||
|
"fs:allow-read-text-file",
|
||||||
|
"fs:allow-write-file",
|
||||||
|
"fs:allow-write-text-file",
|
||||||
|
"fs:allow-read-dir",
|
||||||
|
"fs:allow-copy-file",
|
||||||
|
"fs:allow-mkdir",
|
||||||
|
"fs:allow-remove",
|
||||||
|
"fs:allow-remove",
|
||||||
|
"fs:allow-rename",
|
||||||
|
"fs:allow-exists",
|
||||||
|
"fs:allow-stat",
|
||||||
|
{
|
||||||
|
"identifier": "fs:scope",
|
||||||
|
"allow": [
|
||||||
|
{
|
||||||
|
"path": "$HOME/**/*"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "$HOME/.config"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "$HOME/.config/**/*"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "$APPCONFIG"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "$APPCONFIG/**/*"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "$DOCUMENT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "$DOCUMENT/**/*"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"shell:allow-open",
|
||||||
|
"dialog:allow-open",
|
||||||
|
"dialog:allow-save",
|
||||||
|
"dialog:allow-message",
|
||||||
|
"dialog:allow-ask",
|
||||||
|
"dialog:allow-confirm",
|
||||||
|
{
|
||||||
|
"identifier": "http:default",
|
||||||
|
"allow": [
|
||||||
|
"https://dev.kittycad.io/*",
|
||||||
|
"https://dev.zoo.dev/*",
|
||||||
|
"https://kittycad.io/*",
|
||||||
|
"https://zoo.dev/*",
|
||||||
|
"https://api.dev.kittycad.io/*",
|
||||||
|
"https://api.dev.zoo.dev/*"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"os:allow-platform",
|
||||||
|
"os:allow-version",
|
||||||
|
"os:allow-os-type",
|
||||||
|
"os:allow-family",
|
||||||
|
"os:allow-arch",
|
||||||
|
"os:allow-exe-extension",
|
||||||
|
"os:allow-locale",
|
||||||
|
"os:allow-hostname"
|
||||||
|
],
|
||||||
|
"platforms": [
|
||||||
|
"linux",
|
||||||
|
"macOS",
|
||||||
|
"windows"
|
||||||
|
]
|
||||||
|
}
|
@ -4,11 +4,15 @@
|
|||||||
use std::env;
|
use std::env;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
use std::path::Path;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use oauth2::TokenResponse;
|
use oauth2::TokenResponse;
|
||||||
|
use serde::Serialize;
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
use tauri::{InvokeError, Manager};
|
use tauri::ipc::InvokeError;
|
||||||
|
use tauri_plugin_shell::ShellExt;
|
||||||
const DEFAULT_HOST: &str = "https://api.kittycad.io";
|
const DEFAULT_HOST: &str = "https://api.kittycad.io";
|
||||||
|
|
||||||
/// This command returns the a json string parse from a toml file at the path.
|
/// This command returns the a json string parse from a toml file at the path.
|
||||||
@ -24,6 +28,56 @@ fn read_toml(path: &str) -> Result<String, InvokeError> {
|
|||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// From https://github.com/tauri-apps/tauri/blob/1.x/core/tauri/src/api/dir.rs#L51
|
||||||
|
/// Removed from tauri v2
|
||||||
|
#[derive(Debug, Serialize)]
|
||||||
|
pub struct DiskEntry {
|
||||||
|
/// The path to the entry.
|
||||||
|
pub path: PathBuf,
|
||||||
|
/// The name of the entry (file name with extension or directory name).
|
||||||
|
pub name: Option<String>,
|
||||||
|
/// The children of this entry if it's a directory.
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub children: Option<Vec<DiskEntry>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// From https://github.com/tauri-apps/tauri/blob/1.x/core/tauri/src/api/dir.rs#L51
|
||||||
|
/// Removed from tauri v2
|
||||||
|
fn is_dir<P: AsRef<Path>>(path: P) -> Result<bool> {
|
||||||
|
std::fs::metadata(path)
|
||||||
|
.map(|md| md.is_dir())
|
||||||
|
.map_err(Into::into)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// From https://github.com/tauri-apps/tauri/blob/1.x/core/tauri/src/api/dir.rs#L51
|
||||||
|
/// Removed from tauri v2
|
||||||
|
#[tauri::command]
|
||||||
|
fn read_dir_recursive(path: &str) -> Result<Vec<DiskEntry>, InvokeError> {
|
||||||
|
let mut files_and_dirs: Vec<DiskEntry> = vec![];
|
||||||
|
// let path = path.as_ref();
|
||||||
|
for entry in fs::read_dir(path).map_err(|e| InvokeError::from_anyhow(e.into()))? {
|
||||||
|
let path = entry
|
||||||
|
.map_err(|e| InvokeError::from_anyhow(e.into()))?
|
||||||
|
.path();
|
||||||
|
|
||||||
|
if let Ok(flag) = is_dir(&path) {
|
||||||
|
files_and_dirs.push(DiskEntry {
|
||||||
|
path: path.clone(),
|
||||||
|
children: if flag {
|
||||||
|
Some(read_dir_recursive(path.to_str().expect("No path"))?)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
},
|
||||||
|
name: path
|
||||||
|
.file_name()
|
||||||
|
.map(|name| name.to_string_lossy())
|
||||||
|
.map(|name| name.to_string()),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(files_and_dirs)
|
||||||
|
}
|
||||||
|
|
||||||
/// This command returns a string that is the contents of a file at the path.
|
/// This command returns a string that is the contents of a file at the path.
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
fn read_txt_file(path: &str) -> Result<String, InvokeError> {
|
fn read_txt_file(path: &str) -> Result<String, InvokeError> {
|
||||||
@ -85,7 +139,8 @@ async fn login(app: tauri::AppHandle, host: &str) -> Result<String, InvokeError>
|
|||||||
fs::write("/tmp/kittycad_user_code", details.user_code().secret())
|
fs::write("/tmp/kittycad_user_code", details.user_code().secret())
|
||||||
.expect("Unable to write /tmp/kittycad_user_code file");
|
.expect("Unable to write /tmp/kittycad_user_code file");
|
||||||
} else {
|
} else {
|
||||||
tauri::api::shell::open(&app.shell_scope(), auth_uri.secret(), None)
|
app.shell()
|
||||||
|
.open(auth_uri.secret(), None)
|
||||||
.map_err(|e| InvokeError::from_anyhow(e.into()))?;
|
.map_err(|e| InvokeError::from_anyhow(e.into()))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -165,12 +220,15 @@ fn show_in_folder(path: String) {
|
|||||||
fn main() {
|
fn main() {
|
||||||
tauri::Builder::default()
|
tauri::Builder::default()
|
||||||
.setup(|_app| {
|
.setup(|_app| {
|
||||||
#[cfg(debug_assertions)] // only include this code on debug builds
|
#[cfg(debug_assertions)]
|
||||||
{
|
{
|
||||||
let window = _app.get_window("main").unwrap();
|
use tauri::Manager;
|
||||||
// comment out the below if you don't devtools to open everytime.
|
_app.get_webview("main").unwrap().open_devtools();
|
||||||
// it's useful because otherwise devtools shuts everytime rust code changes.
|
}
|
||||||
window.open_devtools();
|
#[cfg(not(debug_assertions))]
|
||||||
|
{
|
||||||
|
_app.handle()
|
||||||
|
.plugin(tauri_plugin_updater::Builder::new().build())?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
@ -179,9 +237,14 @@ fn main() {
|
|||||||
login,
|
login,
|
||||||
read_toml,
|
read_toml,
|
||||||
read_txt_file,
|
read_txt_file,
|
||||||
|
read_dir_recursive,
|
||||||
show_in_folder,
|
show_in_folder,
|
||||||
])
|
])
|
||||||
.plugin(tauri_plugin_fs_extra::init())
|
.plugin(tauri_plugin_dialog::init())
|
||||||
|
.plugin(tauri_plugin_fs::init())
|
||||||
|
.plugin(tauri_plugin_http::init())
|
||||||
|
.plugin(tauri_plugin_os::init())
|
||||||
|
.plugin(tauri_plugin_shell::init())
|
||||||
.run(tauri::generate_context!())
|
.run(tauri::generate_context!())
|
||||||
.expect("error while running tauri application");
|
.expect("error while running tauri application");
|
||||||
}
|
}
|
||||||
|
@ -1,63 +1,28 @@
|
|||||||
{
|
{
|
||||||
"$schema": "../node_modules/@tauri-apps/cli/schema.json",
|
"$schema": "../node_modules/@tauri-apps/cli/schema.json",
|
||||||
"build": {
|
"app": {
|
||||||
"beforeDevCommand": "yarn start",
|
"security": {
|
||||||
"devPath": "http://localhost:3000",
|
"csp": null
|
||||||
"distDir": "../build"
|
|
||||||
},
|
},
|
||||||
"package": {
|
"windows": [
|
||||||
"productName": "zoo-modeling-app",
|
{
|
||||||
"version": "0.17.3"
|
"fullscreen": false,
|
||||||
},
|
"height": 1200,
|
||||||
"tauri": {
|
"resizable": true,
|
||||||
"allowlist": {
|
"title": "Zoo Modeling App",
|
||||||
"all": false,
|
"width": 1800
|
||||||
"dialog": {
|
}
|
||||||
"all": true,
|
|
||||||
"ask": true,
|
|
||||||
"confirm": true,
|
|
||||||
"message": true,
|
|
||||||
"open": true,
|
|
||||||
"save": true
|
|
||||||
},
|
|
||||||
"fs": {
|
|
||||||
"scope": [
|
|
||||||
"$HOME/**/*",
|
|
||||||
"$APPCONFIG",
|
|
||||||
"$APPCONFIG/**/*",
|
|
||||||
"$DOCUMENT",
|
|
||||||
"$DOCUMENT/**/*"
|
|
||||||
],
|
|
||||||
"all": true
|
|
||||||
},
|
|
||||||
"http": {
|
|
||||||
"request": true,
|
|
||||||
"scope": [
|
|
||||||
"https://dev.kittycad.io/*",
|
|
||||||
"https://dev.zoo.dev/*",
|
|
||||||
"https://kittycad.io/*",
|
|
||||||
"https://zoo.dev/*",
|
|
||||||
"https://api.dev.kittycad.io/*",
|
|
||||||
"https://api.dev.zoo.dev/*"
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"os": {
|
"build": {
|
||||||
"all": true
|
"beforeDevCommand": "yarn start",
|
||||||
},
|
"devUrl": "http://localhost:3000",
|
||||||
"shell": {
|
"frontendDist": "../build"
|
||||||
"open": true
|
|
||||||
},
|
|
||||||
"path": {
|
|
||||||
"all": true
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"bundle": {
|
"bundle": {
|
||||||
"active": true,
|
"active": true,
|
||||||
"category": "DeveloperTool",
|
"category": "DeveloperTool",
|
||||||
"copyright": "",
|
"copyright": "",
|
||||||
"deb": {
|
|
||||||
"depends": []
|
|
||||||
},
|
|
||||||
"externalBin": [],
|
"externalBin": [],
|
||||||
"icon": [
|
"icon": [
|
||||||
"icons/32x32.png",
|
"icons/32x32.png",
|
||||||
@ -66,7 +31,11 @@
|
|||||||
"icons/icon.icns",
|
"icons/icon.icns",
|
||||||
"icons/icon.ico"
|
"icons/icon.ico"
|
||||||
],
|
],
|
||||||
"identifier": "dev.zoo.modeling-app",
|
"linux": {
|
||||||
|
"deb": {
|
||||||
|
"depends": []
|
||||||
|
}
|
||||||
|
},
|
||||||
"longDescription": "",
|
"longDescription": "",
|
||||||
"macOS": {
|
"macOS": {
|
||||||
"entitlements": null,
|
"entitlements": null,
|
||||||
@ -79,20 +48,12 @@
|
|||||||
"shortDescription": "",
|
"shortDescription": "",
|
||||||
"targets": "all"
|
"targets": "all"
|
||||||
},
|
},
|
||||||
"security": {
|
"identifier": "dev.zoo.modeling-app",
|
||||||
"csp": null
|
"plugins": {
|
||||||
},
|
"shell": {
|
||||||
"updater": {
|
"open": true
|
||||||
"active": false
|
|
||||||
},
|
|
||||||
"windows": [
|
|
||||||
{
|
|
||||||
"fullscreen": false,
|
|
||||||
"height": 1200,
|
|
||||||
"resizable": true,
|
|
||||||
"title": "Zoo Modeling App",
|
|
||||||
"width": 1800
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"productName": "Zoo Modeling App",
|
||||||
|
"version": "0.17.3"
|
||||||
}
|
}
|
||||||
|
@ -1,6 +0,0 @@
|
|||||||
{
|
|
||||||
"$schema": "../node_modules/@tauri-apps/cli/schema.json",
|
|
||||||
"package": {
|
|
||||||
"productName": "Zoo Modeling App"
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,6 +1,13 @@
|
|||||||
{
|
{
|
||||||
"$schema": "../node_modules/@tauri-apps/cli/schema.json",
|
"$schema": "../node_modules/@tauri-apps/cli/schema.json",
|
||||||
"tauri": {
|
"bundle": {
|
||||||
|
"windows": {
|
||||||
|
"certificateThumbprint": "F4C9A52FF7BC26EE5E054946F6B11DEEA94C748D",
|
||||||
|
"digestAlgorithm": "sha256",
|
||||||
|
"timestampUrl": "http://timestamp.digicert.com"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"plugins": {
|
||||||
"updater": {
|
"updater": {
|
||||||
"active": true,
|
"active": true,
|
||||||
"endpoints": [
|
"endpoints": [
|
||||||
@ -8,14 +15,6 @@
|
|||||||
],
|
],
|
||||||
"dialog": true,
|
"dialog": true,
|
||||||
"pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IEUzNzA4MjBEQjFBRTY4NzYKUldSMmFLNnhEWUp3NCtsT21Jd05wQktOaGVkOVp6MUFma0hNTDRDSnI2RkJJTEZOWG1ncFhqcU8K"
|
"pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IEUzNzA4MjBEQjFBRTY4NzYKUldSMmFLNnhEWUp3NCtsT21Jd05wQktOaGVkOVp6MUFma0hNTDRDSnI2RkJJTEZOWG1ncFhqcU8K"
|
||||||
},
|
|
||||||
"bundle": {
|
|
||||||
"identifier": "io.kittycad.modeling-app",
|
|
||||||
"windows": {
|
|
||||||
"certificateThumbprint": "F4C9A52FF7BC26EE5E054946F6B11DEEA94C748D",
|
|
||||||
"digestAlgorithm": "sha256",
|
|
||||||
"timestampUrl": "http://timestamp.digicert.com"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +0,0 @@
|
|||||||
{
|
|
||||||
"$schema": "../node_modules/@tauri-apps/cli/schema.json",
|
|
||||||
"package": {
|
|
||||||
"productName": "Zoo Modeling App"
|
|
||||||
}
|
|
||||||
}
|
|
@ -254,7 +254,7 @@ export const Toolbar = () => {
|
|||||||
onClick={() => commandBarSend({ type: 'Open' })}
|
onClick={() => commandBarSend({ type: 'Open' })}
|
||||||
className="rounded-r-full pr-4 self-stretch border-primary/30 hover:border-primary dark:border-chalkboard-80 dark:bg-chalkboard-80 text-primary"
|
className="rounded-r-full pr-4 self-stretch border-primary/30 hover:border-primary dark:border-chalkboard-80 dark:bg-chalkboard-80 text-primary"
|
||||||
>
|
>
|
||||||
{platform === 'darwin' ? '⌘K' : 'Ctrl+/'}
|
{platform === 'macos' ? '⌘K' : 'Ctrl+/'}
|
||||||
</ActionButton>
|
</ActionButton>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
@ -54,7 +54,7 @@ export const AppHeader = ({
|
|||||||
>
|
>
|
||||||
Command Palette{' '}
|
Command Palette{' '}
|
||||||
<kbd className="bg-primary/10 dark:bg-chalkboard-100 dark:text-primary inline-block px-1 py-0.5 border-primary dark:border-chalkboard-90">
|
<kbd className="bg-primary/10 dark:bg-chalkboard-100 dark:text-primary inline-block px-1 py-0.5 border-primary dark:border-chalkboard-90">
|
||||||
{platform === 'darwin' ? '⌘K' : 'Ctrl+/'}
|
{platform === 'macos' ? '⌘K' : 'Ctrl+/'}
|
||||||
</kbd>
|
</kbd>
|
||||||
</ActionButton>
|
</ActionButton>
|
||||||
)}
|
)}
|
||||||
|
@ -14,16 +14,10 @@ import {
|
|||||||
} from 'xstate'
|
} from 'xstate'
|
||||||
import { useCommandsContext } from 'hooks/useCommandsContext'
|
import { useCommandsContext } from 'hooks/useCommandsContext'
|
||||||
import { fileMachine } from 'machines/fileMachine'
|
import { fileMachine } from 'machines/fileMachine'
|
||||||
import {
|
import { mkdir, remove, rename, create } from '@tauri-apps/plugin-fs'
|
||||||
createDir,
|
|
||||||
removeDir,
|
|
||||||
removeFile,
|
|
||||||
renameFile,
|
|
||||||
writeFile,
|
|
||||||
} from '@tauri-apps/api/fs'
|
|
||||||
import { readProject } from 'lib/tauriFS'
|
import { readProject } from 'lib/tauriFS'
|
||||||
import { isTauri } from 'lib/isTauri'
|
import { isTauri } from 'lib/isTauri'
|
||||||
import { sep } from '@tauri-apps/api/path'
|
import { join, sep } from '@tauri-apps/api/path'
|
||||||
import { DEFAULT_FILE_NAME, FILE_EXT } from 'lib/constants'
|
import { DEFAULT_FILE_NAME, FILE_EXT } from 'lib/constants'
|
||||||
|
|
||||||
type MachineContext<T extends AnyStateMachine> = {
|
type MachineContext<T extends AnyStateMachine> = {
|
||||||
@ -56,7 +50,7 @@ export const FileMachineProvider = ({
|
|||||||
commandBarSend({ type: 'Close' })
|
commandBarSend({ type: 'Close' })
|
||||||
navigate(
|
navigate(
|
||||||
`${paths.FILE}/${encodeURIComponent(
|
`${paths.FILE}/${encodeURIComponent(
|
||||||
context.selectedDirectory + sep + event.data.name
|
context.selectedDirectory + sep() + event.data.name
|
||||||
)}`
|
)}`
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -79,14 +73,13 @@ export const FileMachineProvider = ({
|
|||||||
let name = event.data.name.trim() || DEFAULT_FILE_NAME
|
let name = event.data.name.trim() || DEFAULT_FILE_NAME
|
||||||
|
|
||||||
if (event.data.makeDir) {
|
if (event.data.makeDir) {
|
||||||
await createDir(context.selectedDirectory.path + sep + name)
|
await mkdir(await join(context.selectedDirectory.path, name))
|
||||||
} else {
|
} else {
|
||||||
await writeFile(
|
await create(
|
||||||
context.selectedDirectory.path +
|
context.selectedDirectory.path +
|
||||||
sep +
|
sep() +
|
||||||
name +
|
name +
|
||||||
(name.endsWith(FILE_EXT) ? '' : FILE_EXT),
|
(name.endsWith(FILE_EXT) ? '' : FILE_EXT)
|
||||||
''
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,12 +92,11 @@ export const FileMachineProvider = ({
|
|||||||
const { oldName, newName, isDir } = event.data
|
const { oldName, newName, isDir } = event.data
|
||||||
let name = newName ? newName : DEFAULT_FILE_NAME
|
let name = newName ? newName : DEFAULT_FILE_NAME
|
||||||
|
|
||||||
await renameFile(
|
await rename(
|
||||||
context.selectedDirectory.path + sep + oldName,
|
await join(context.selectedDirectory.path, oldName),
|
||||||
context.selectedDirectory.path +
|
(await join(context.selectedDirectory.path, name)) +
|
||||||
sep +
|
(name.endsWith(FILE_EXT) || isDir ? '' : FILE_EXT),
|
||||||
name +
|
{}
|
||||||
(name.endsWith(FILE_EXT) || isDir ? '' : FILE_EXT)
|
|
||||||
)
|
)
|
||||||
return (
|
return (
|
||||||
oldName !== name && `Successfully renamed "${oldName}" to "${name}"`
|
oldName !== name && `Successfully renamed "${oldName}" to "${name}"`
|
||||||
@ -117,11 +109,11 @@ export const FileMachineProvider = ({
|
|||||||
const isDir = !!event.data.children
|
const isDir = !!event.data.children
|
||||||
|
|
||||||
if (isDir) {
|
if (isDir) {
|
||||||
await removeDir(event.data.path, {
|
await remove(event.data.path, {
|
||||||
recursive: true,
|
recursive: true,
|
||||||
}).catch((e) => console.error('Error deleting directory', e))
|
}).catch((e) => console.error('Error deleting directory', e))
|
||||||
} else {
|
} else {
|
||||||
await removeFile(event.data.path).catch((e) =>
|
await remove(event.data.path).catch((e) =>
|
||||||
console.error('Error deleting file', e)
|
console.error('Error deleting file', e)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
import { type IndexLoaderData } from 'lib/types'
|
import type { FileEntry, IndexLoaderData } from 'lib/types'
|
||||||
import { paths } from 'lib/paths'
|
import { paths } from 'lib/paths'
|
||||||
import { ActionButton } from './ActionButton'
|
import { ActionButton } from './ActionButton'
|
||||||
import Tooltip from './Tooltip'
|
import Tooltip from './Tooltip'
|
||||||
import { FileEntry } from '@tauri-apps/api/fs'
|
|
||||||
import { Dispatch, useEffect, useRef, useState } from 'react'
|
import { Dispatch, useEffect, useRef, useState } from 'react'
|
||||||
import { useNavigate } from 'react-router-dom'
|
import { useNavigate } from 'react-router-dom'
|
||||||
import { Dialog, Disclosure } from '@headlessui/react'
|
import { Dialog, Disclosure } from '@headlessui/react'
|
||||||
|
@ -13,7 +13,7 @@ import { Extension } from '@codemirror/state'
|
|||||||
import { LanguageSupport } from '@codemirror/language'
|
import { LanguageSupport } from '@codemirror/language'
|
||||||
import { useNavigate } from 'react-router-dom'
|
import { useNavigate } from 'react-router-dom'
|
||||||
import { paths } from 'lib/paths'
|
import { paths } from 'lib/paths'
|
||||||
import { FileEntry } from '@tauri-apps/api/fs'
|
import { FileEntry } from 'lib/types'
|
||||||
|
|
||||||
const DEFAULT_FILE_NAME: string = 'main.kcl'
|
const DEFAULT_FILE_NAME: string = 'main.kcl'
|
||||||
|
|
||||||
|
@ -136,7 +136,10 @@ function ProjectCard({
|
|||||||
}`}
|
}`}
|
||||||
</span>
|
</span>
|
||||||
<span className="text-chalkboard-60 text-xs">
|
<span className="text-chalkboard-60 text-xs">
|
||||||
Edited {getDisplayedTime(project.entrypointMetadata.modifiedAt)}
|
Edited{' '}
|
||||||
|
{project.entrypointMetadata.mtime
|
||||||
|
? getDisplayedTime(project.entrypointMetadata.mtime)
|
||||||
|
: 'never'}
|
||||||
</span>
|
</span>
|
||||||
<div className="absolute z-10 bottom-2 right-2 flex gap-1 items-center opacity-0 group-hover:opacity-100 group-focus-within:opacity-100">
|
<div className="absolute z-10 bottom-2 right-2 flex gap-1 items-center opacity-0 group-hover:opacity-100 group-focus-within:opacity-100">
|
||||||
<ActionButton
|
<ActionButton
|
||||||
|
@ -17,23 +17,24 @@ const projectWellFormed = {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
entrypointMetadata: {
|
entrypointMetadata: {
|
||||||
accessedAt: now,
|
atime: now,
|
||||||
blksize: 32,
|
blksize: 32,
|
||||||
blocks: 32,
|
blocks: 32,
|
||||||
createdAt: now,
|
birthtime: now,
|
||||||
dev: 1,
|
dev: 1,
|
||||||
gid: 1,
|
gid: 1,
|
||||||
ino: 1,
|
ino: 1,
|
||||||
isDir: false,
|
isDirectory: false,
|
||||||
isFile: true,
|
isFile: true,
|
||||||
isSymlink: false,
|
isSymlink: false,
|
||||||
mode: 1,
|
mode: 1,
|
||||||
modifiedAt: now,
|
mtime: now,
|
||||||
nlink: 1,
|
nlink: 1,
|
||||||
permissions: { readonly: false, mode: 1 },
|
readonly: false,
|
||||||
rdev: 1,
|
rdev: 1,
|
||||||
size: 32,
|
size: 32,
|
||||||
uid: 1,
|
uid: 1,
|
||||||
|
fileAttributes: null,
|
||||||
},
|
},
|
||||||
} satisfies ProjectWithEntryPointMetadata
|
} satisfies ProjectWithEntryPointMetadata
|
||||||
|
|
||||||
|
@ -87,7 +87,7 @@ function ProjectMenuPopover({
|
|||||||
<div className="flex flex-col items-start py-0.5">
|
<div className="flex flex-col items-start py-0.5">
|
||||||
<span className="hidden text-sm text-chalkboard-110 dark:text-chalkboard-20 whitespace-nowrap lg:block">
|
<span className="hidden text-sm text-chalkboard-110 dark:text-chalkboard-20 whitespace-nowrap lg:block">
|
||||||
{isTauri() && file?.name
|
{isTauri() && file?.name
|
||||||
? file.name.slice(file.name.lastIndexOf(sep) + 1)
|
? file.name.slice(file.name.lastIndexOf(sep()) + 1)
|
||||||
: APP_NAME}
|
: APP_NAME}
|
||||||
</span>
|
</span>
|
||||||
{isTauri() && project?.name && (
|
{isTauri() && project?.name && (
|
||||||
@ -135,7 +135,7 @@ function ProjectMenuPopover({
|
|||||||
data-testid="createdAt"
|
data-testid="createdAt"
|
||||||
>
|
>
|
||||||
Created{' '}
|
Created{' '}
|
||||||
{project.entrypointMetadata.createdAt.toLocaleDateString()}
|
{project.entrypointMetadata.birthtime?.toLocaleDateString()}
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Platform, platform } from '@tauri-apps/api/os'
|
import { Platform, platform } from '@tauri-apps/plugin-os'
|
||||||
import { isTauri } from 'lib/isTauri'
|
import { isTauri } from 'lib/isTauri'
|
||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
|
|
||||||
@ -14,9 +14,9 @@ export default function usePlatform() {
|
|||||||
void getPlatform()
|
void getPlatform()
|
||||||
} else {
|
} else {
|
||||||
if (navigator.userAgent.indexOf('Mac') !== -1) {
|
if (navigator.userAgent.indexOf('Mac') !== -1) {
|
||||||
setPlatformName('darwin')
|
setPlatformName('macos')
|
||||||
} else if (navigator.userAgent.indexOf('Win') !== -1) {
|
} else if (navigator.userAgent.indexOf('Win') !== -1) {
|
||||||
setPlatformName('win32')
|
setPlatformName('windows')
|
||||||
} else if (navigator.userAgent.indexOf('Linux') !== -1) {
|
} else if (navigator.userAgent.indexOf('Linux') !== -1) {
|
||||||
setPlatformName('linux')
|
setPlatformName('linux')
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ import { bracket } from 'lib/exampleKcl'
|
|||||||
import { getNodeFromPath } from './queryAst'
|
import { getNodeFromPath } from './queryAst'
|
||||||
import { Params } from 'react-router-dom'
|
import { Params } from 'react-router-dom'
|
||||||
import { isTauri } from 'lib/isTauri'
|
import { isTauri } from 'lib/isTauri'
|
||||||
import { writeTextFile } from '@tauri-apps/api/fs'
|
import { writeTextFile } from '@tauri-apps/plugin-fs'
|
||||||
import { toast } from 'react-hot-toast'
|
import { toast } from 'react-hot-toast'
|
||||||
|
|
||||||
const PERSIST_CODE_TOKEN = 'persistCode'
|
const PERSIST_CODE_TOKEN = 'persistCode'
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
import {
|
import { readFile, exists as tauriExists } from '@tauri-apps/plugin-fs'
|
||||||
readDir,
|
|
||||||
readBinaryFile,
|
|
||||||
exists as tauriExists,
|
|
||||||
} from '@tauri-apps/api/fs'
|
|
||||||
import { isTauri } from 'lib/isTauri'
|
import { isTauri } from 'lib/isTauri'
|
||||||
import { join } from '@tauri-apps/api/path'
|
import { join } from '@tauri-apps/api/path'
|
||||||
|
import { invoke } from '@tauri-apps/api/core'
|
||||||
|
import { FileEntry } from 'lib/types'
|
||||||
|
|
||||||
/// FileSystemManager is a class that provides a way to read files from the local file system.
|
/// FileSystemManager is a class that provides a way to read files from the local file system.
|
||||||
/// It assumes that you are in a project since it is solely used by the std lib
|
/// It assumes that you are in a project since it is solely used by the std lib
|
||||||
@ -37,7 +35,7 @@ class FileSystemManager {
|
|||||||
throw new Error(`Error reading file: ${error}`)
|
throw new Error(`Error reading file: ${error}`)
|
||||||
})
|
})
|
||||||
.then((file) => {
|
.then((file) => {
|
||||||
return readBinaryFile(file)
|
return readFile(file)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,7 +69,9 @@ class FileSystemManager {
|
|||||||
throw new Error(`Error joining dir: ${error}`)
|
throw new Error(`Error joining dir: ${error}`)
|
||||||
})
|
})
|
||||||
.then((p) => {
|
.then((p) => {
|
||||||
readDir(p, { recursive: true })
|
invoke<FileEntry[]>('read_dir_recursive', {
|
||||||
|
path: p,
|
||||||
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw new Error(`Error reading dir: ${error}`)
|
throw new Error(`Error reading dir: ${error}`)
|
||||||
})
|
})
|
||||||
|
@ -78,7 +78,7 @@ const initialise = async () => {
|
|||||||
: window.location.origin.includes('tauri://localhost')
|
: window.location.origin.includes('tauri://localhost')
|
||||||
? 'tauri://localhost' // custom protocol for macOS
|
? 'tauri://localhost' // custom protocol for macOS
|
||||||
: window.location.origin.includes('tauri.localhost')
|
: window.location.origin.includes('tauri.localhost')
|
||||||
? 'https://tauri.localhost' // fallback for Windows
|
? 'http://tauri.localhost' // fallback for Windows
|
||||||
: window.location.origin.includes('localhost')
|
: window.location.origin.includes('localhost')
|
||||||
? 'http://localhost:3000'
|
? 'http://localhost:3000'
|
||||||
: window.location.origin && window.location.origin !== 'null'
|
: window.location.origin && window.location.origin !== 'null'
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { isTauri } from './isTauri'
|
import { isTauri } from './isTauri'
|
||||||
import { deserialize_files } from '../wasm-lib/pkg/wasm_lib'
|
import { deserialize_files } from '../wasm-lib/pkg/wasm_lib'
|
||||||
import { browserSaveFile } from './browserSaveFile'
|
import { browserSaveFile } from './browserSaveFile'
|
||||||
import { save } from '@tauri-apps/api/dialog'
|
import { save } from '@tauri-apps/plugin-dialog'
|
||||||
import { writeBinaryFile } from '@tauri-apps/api/fs'
|
import { writeFile } from '@tauri-apps/plugin-fs'
|
||||||
|
|
||||||
import JSZip from 'jszip'
|
import JSZip from 'jszip'
|
||||||
|
|
||||||
@ -26,7 +26,7 @@ const save_ = async (file: ModelingAppFile) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Write the file.
|
// Write the file.
|
||||||
await writeBinaryFile(filePath, file.contents)
|
await writeFile(filePath, new Uint8Array(file.contents))
|
||||||
} else {
|
} else {
|
||||||
// Download the file to the user's computer.
|
// Download the file to the user's computer.
|
||||||
// Now we need to download the files to the user's downloads folder.
|
// Now we need to download the files to the user's downloads folder.
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
export function isTauri(): boolean {
|
export function isTauri(): boolean {
|
||||||
if (globalThis.window && typeof globalThis.window !== 'undefined') {
|
if (globalThis.window && typeof globalThis.window !== 'undefined') {
|
||||||
return '__TAURI__' in globalThis.window
|
return '__TAURI_INTERNALS__' in globalThis.window
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ export const BROWSER_PATH = `%2F${BROWSER_PROJECT_NAME}%2F${BROWSER_FILE_NAME}${
|
|||||||
|
|
||||||
export function getProjectMetaByRouteId(id?: string, defaultDir = '') {
|
export function getProjectMetaByRouteId(id?: string, defaultDir = '') {
|
||||||
if (!id) return undefined
|
if (!id) return undefined
|
||||||
const s = isTauri() ? sep : '/'
|
const s = isTauri() ? sep() : '/'
|
||||||
|
|
||||||
const decodedId = decodeURIComponent(id).replace(/\/$/, '') // remove trailing slash
|
const decodedId = decodeURIComponent(id).replace(/\/$/, '') // remove trailing slash
|
||||||
const projectAndFile =
|
const projectAndFile =
|
||||||
|
@ -1,5 +1,10 @@
|
|||||||
import { ActionFunction, LoaderFunction, redirect } from 'react-router-dom'
|
import { ActionFunction, LoaderFunction, redirect } from 'react-router-dom'
|
||||||
import { FileLoaderData, HomeLoaderData, IndexLoaderData } from './types'
|
import {
|
||||||
|
FileEntry,
|
||||||
|
FileLoaderData,
|
||||||
|
HomeLoaderData,
|
||||||
|
IndexLoaderData,
|
||||||
|
} from './types'
|
||||||
import { isTauri } from './isTauri'
|
import { isTauri } from './isTauri'
|
||||||
import { getProjectMetaByRouteId, paths } from './paths'
|
import { getProjectMetaByRouteId, paths } from './paths'
|
||||||
import { BROWSER_PATH } from 'lib/paths'
|
import { BROWSER_PATH } from 'lib/paths'
|
||||||
@ -15,11 +20,11 @@ import {
|
|||||||
initializeProjectDirectory,
|
initializeProjectDirectory,
|
||||||
} from './tauriFS'
|
} from './tauriFS'
|
||||||
import makeUrlPathRelative from './makeUrlPathRelative'
|
import makeUrlPathRelative from './makeUrlPathRelative'
|
||||||
import { sep } from '@tauri-apps/api/path'
|
import { join, sep } from '@tauri-apps/api/path'
|
||||||
import { readDir, readTextFile } from '@tauri-apps/api/fs'
|
import { readTextFile, stat } from '@tauri-apps/plugin-fs'
|
||||||
import { metadata } from 'tauri-plugin-fs-extra-api'
|
|
||||||
import { kclManager } from 'lib/singletons'
|
import { kclManager } from 'lib/singletons'
|
||||||
import { fileSystemManager } from 'lang/std/fileSystemManager'
|
import { fileSystemManager } from 'lang/std/fileSystemManager'
|
||||||
|
import { invoke } from '@tauri-apps/api/core'
|
||||||
|
|
||||||
// The root loader simply resolves the settings and any errors that
|
// The root loader simply resolves the settings and any errors that
|
||||||
// occurred during the settings load
|
// occurred during the settings load
|
||||||
@ -81,7 +86,7 @@ export const fileLoader: LoaderFunction = async ({
|
|||||||
if (!currentFileName || !currentFilePath) {
|
if (!currentFileName || !currentFilePath) {
|
||||||
return redirect(
|
return redirect(
|
||||||
`${paths.FILE}/${encodeURIComponent(
|
`${paths.FILE}/${encodeURIComponent(
|
||||||
`${params.id}${isTauri() ? sep : '/'}${PROJECT_ENTRYPOINT}`
|
`${params.id}${isTauri() ? sep() : '/'}${PROJECT_ENTRYPOINT}`
|
||||||
)}`
|
)}`
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -89,10 +94,12 @@ export const fileLoader: LoaderFunction = async ({
|
|||||||
// TODO: PROJECT_ENTRYPOINT is hardcoded
|
// TODO: PROJECT_ENTRYPOINT is hardcoded
|
||||||
// until we support setting a project's entrypoint file
|
// until we support setting a project's entrypoint file
|
||||||
const code = await readTextFile(currentFilePath)
|
const code = await readTextFile(currentFilePath)
|
||||||
const entrypointMetadata = await metadata(
|
const entrypointMetadata = await stat(
|
||||||
projectPath + sep + PROJECT_ENTRYPOINT
|
await join(projectPath, PROJECT_ENTRYPOINT)
|
||||||
)
|
)
|
||||||
const children = await readDir(projectPath, { recursive: true })
|
const children = await invoke<FileEntry[]>('read_dir_recursive', {
|
||||||
|
path: projectPath,
|
||||||
|
})
|
||||||
kclManager.setCodeAndExecute(code, false)
|
kclManager.setCodeAndExecute(code, false)
|
||||||
|
|
||||||
// Set the file system manager to the project path
|
// Set the file system manager to the project path
|
||||||
|
@ -14,7 +14,7 @@ import {
|
|||||||
} from 'lib/cameraControls'
|
} from 'lib/cameraControls'
|
||||||
import { isTauri } from 'lib/isTauri'
|
import { isTauri } from 'lib/isTauri'
|
||||||
import { useRef } from 'react'
|
import { useRef } from 'react'
|
||||||
import { open } from '@tauri-apps/api/dialog'
|
import { open } from '@tauri-apps/plugin-dialog'
|
||||||
import { CustomIcon } from 'components/CustomIcon'
|
import { CustomIcon } from 'components/CustomIcon'
|
||||||
import Tooltip from 'components/Tooltip'
|
import Tooltip from 'components/Tooltip'
|
||||||
|
|
||||||
|
@ -6,9 +6,8 @@ import {
|
|||||||
import { Setting, createSettings, settings } from 'lib/settings/initialSettings'
|
import { Setting, createSettings, settings } from 'lib/settings/initialSettings'
|
||||||
import { SaveSettingsPayload, SettingsLevel } from './settingsTypes'
|
import { SaveSettingsPayload, SettingsLevel } from './settingsTypes'
|
||||||
import { isTauri } from 'lib/isTauri'
|
import { isTauri } from 'lib/isTauri'
|
||||||
import { removeFile, writeTextFile } from '@tauri-apps/api/fs'
|
|
||||||
import { exists } from 'tauri-plugin-fs-extra-api'
|
|
||||||
import * as TOML from '@iarna/toml'
|
import * as TOML from '@iarna/toml'
|
||||||
|
import { remove, writeTextFile, exists } from '@tauri-apps/plugin-fs'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* We expect the settings to be stored in a TOML file
|
* We expect the settings to be stored in a TOML file
|
||||||
@ -91,7 +90,7 @@ async function writeOrClearPersistedSettings(
|
|||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
if (isTauri() && (await exists(settingsFilePath))) {
|
if (isTauri() && (await exists(settingsFilePath))) {
|
||||||
await removeFile(settingsFilePath)
|
await remove(settingsFilePath)
|
||||||
}
|
}
|
||||||
localStorage.removeItem(settingsFilePath)
|
localStorage.removeItem(settingsFilePath)
|
||||||
}
|
}
|
||||||
|
@ -43,12 +43,12 @@ export function getSortFunction(sortBy: string) {
|
|||||||
a: ProjectWithEntryPointMetadata,
|
a: ProjectWithEntryPointMetadata,
|
||||||
b: ProjectWithEntryPointMetadata
|
b: ProjectWithEntryPointMetadata
|
||||||
) => {
|
) => {
|
||||||
if (a.entrypointMetadata?.modifiedAt && b.entrypointMetadata?.modifiedAt) {
|
if (a.entrypointMetadata?.mtime && b.entrypointMetadata?.mtime) {
|
||||||
return !sortBy || sortBy.includes('desc')
|
return !sortBy || sortBy.includes('desc')
|
||||||
? b.entrypointMetadata.modifiedAt.getTime() -
|
? b.entrypointMetadata.mtime.getTime() -
|
||||||
a.entrypointMetadata.modifiedAt.getTime()
|
a.entrypointMetadata.mtime.getTime()
|
||||||
: a.entrypointMetadata.modifiedAt.getTime() -
|
: a.entrypointMetadata.mtime.getTime() -
|
||||||
b.entrypointMetadata.modifiedAt.getTime()
|
b.entrypointMetadata.mtime.getTime()
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import { FileEntry } from '@tauri-apps/api/fs'
|
|
||||||
import {
|
import {
|
||||||
deepFileFilter,
|
deepFileFilter,
|
||||||
getNextProjectIndex,
|
getNextProjectIndex,
|
||||||
@ -6,6 +5,7 @@ import {
|
|||||||
interpolateProjectNameWithIndex,
|
interpolateProjectNameWithIndex,
|
||||||
isRelevantFileOrDir,
|
isRelevantFileOrDir,
|
||||||
} from './tauriFS'
|
} from './tauriFS'
|
||||||
|
import type { FileEntry } from './types'
|
||||||
import { MAX_PADDING } from './constants'
|
import { MAX_PADDING } from './constants'
|
||||||
|
|
||||||
describe('Test project name utility functions', () => {
|
describe('Test project name utility functions', () => {
|
||||||
|
@ -1,15 +1,20 @@
|
|||||||
import {
|
import {
|
||||||
FileEntry,
|
mkdir,
|
||||||
createDir,
|
|
||||||
exists,
|
exists,
|
||||||
readDir,
|
|
||||||
readTextFile,
|
readTextFile,
|
||||||
writeTextFile,
|
writeTextFile,
|
||||||
} from '@tauri-apps/api/fs'
|
stat,
|
||||||
import { appConfigDir, documentDir, homeDir, sep } from '@tauri-apps/api/path'
|
} from '@tauri-apps/plugin-fs'
|
||||||
|
import { invoke } from '@tauri-apps/api/core'
|
||||||
|
import {
|
||||||
|
appConfigDir,
|
||||||
|
documentDir,
|
||||||
|
homeDir,
|
||||||
|
join,
|
||||||
|
sep,
|
||||||
|
} from '@tauri-apps/api/path'
|
||||||
import { isTauri } from './isTauri'
|
import { isTauri } from './isTauri'
|
||||||
import { type ProjectWithEntryPointMetadata } from 'lib/types'
|
import type { FileEntry, ProjectWithEntryPointMetadata } from 'lib/types'
|
||||||
import { metadata } from 'tauri-plugin-fs-extra-api'
|
|
||||||
import {
|
import {
|
||||||
FILE_EXT,
|
FILE_EXT,
|
||||||
INDEX_IDENTIFIER,
|
INDEX_IDENTIFIER,
|
||||||
@ -33,10 +38,10 @@ export async function getInitialDefaultDir() {
|
|||||||
try {
|
try {
|
||||||
dir = await documentDir()
|
dir = await documentDir()
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
dir = `${await homeDir()}Documents/` // for headless Linux (eg. Github Actions)
|
dir = await join(await homeDir(), 'Documents') // for headless Linux (eg. Github Actions)
|
||||||
}
|
}
|
||||||
|
|
||||||
return dir + PROJECT_FOLDER
|
return await join(dir, PROJECT_FOLDER)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initializes the project directory and returns the path
|
// Initializes the project directory and returns the path
|
||||||
@ -96,7 +101,7 @@ async function testAndCreateDir(
|
|||||||
if (dirExists instanceof Error) {
|
if (dirExists instanceof Error) {
|
||||||
returnValue.error = dirExists
|
returnValue.error = dirExists
|
||||||
} else if (dirExists === false) {
|
} else if (dirExists === false) {
|
||||||
const newDirCreated = await createDir(directory, { recursive: true }).catch(
|
const newDirCreated = await mkdir(directory, { recursive: true }).catch(
|
||||||
(e) => {
|
(e) => {
|
||||||
console.error(
|
console.error(
|
||||||
`Error creating directory ${directory}. Original error:`,
|
`Error creating directory ${directory}. Original error:`,
|
||||||
@ -129,14 +134,12 @@ export function isProjectDirectory(fileOrDir: Partial<FileEntry>) {
|
|||||||
// and return the valid projects
|
// and return the valid projects
|
||||||
export async function getProjectsInDir(projectDir: string) {
|
export async function getProjectsInDir(projectDir: string) {
|
||||||
const readProjects = (
|
const readProjects = (
|
||||||
await readDir(projectDir, {
|
await invoke<FileEntry[]>('read_dir_recursive', { path: projectDir })
|
||||||
recursive: true,
|
|
||||||
})
|
|
||||||
).filter(isProjectDirectory)
|
).filter(isProjectDirectory)
|
||||||
|
|
||||||
const projectsWithMetadata = await Promise.all(
|
const projectsWithMetadata = await Promise.all(
|
||||||
readProjects.map(async (p) => ({
|
readProjects.map(async (p) => ({
|
||||||
entrypointMetadata: await metadata(p.path + sep + PROJECT_ENTRYPOINT),
|
entrypointMetadata: await stat(await join(p.path, PROJECT_ENTRYPOINT)),
|
||||||
...p,
|
...p,
|
||||||
}))
|
}))
|
||||||
)
|
)
|
||||||
@ -196,8 +199,8 @@ export function deepFileFilterFlat(
|
|||||||
// Read the contents of a project directory
|
// Read the contents of a project directory
|
||||||
// and return all relevant files and sub-directories recursively
|
// and return all relevant files and sub-directories recursively
|
||||||
export async function readProject(projectDir: string) {
|
export async function readProject(projectDir: string) {
|
||||||
const readFiles = await readDir(projectDir, {
|
const readFiles = await invoke<FileEntry[]>('read_dir_recursive', {
|
||||||
recursive: true,
|
path: projectDir,
|
||||||
})
|
})
|
||||||
|
|
||||||
return deepFileFilter(readFiles, isRelevantFileOrDir)
|
return deepFileFilter(readFiles, isRelevantFileOrDir)
|
||||||
@ -285,29 +288,29 @@ export async function createNewProject(
|
|||||||
|
|
||||||
const dirExists = await exists(path)
|
const dirExists = await exists(path)
|
||||||
if (!dirExists) {
|
if (!dirExists) {
|
||||||
await createDir(path, { recursive: true }).catch((err) => {
|
await mkdir(path, { recursive: true }).catch((err) => {
|
||||||
console.error('Error creating new directory:', err)
|
console.error('Error creating new directory:', err)
|
||||||
throw err
|
throw err
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
await writeTextFile(path + sep + PROJECT_ENTRYPOINT, initCode).catch(
|
await writeTextFile(await join(path, PROJECT_ENTRYPOINT), initCode).catch(
|
||||||
(err) => {
|
(err) => {
|
||||||
console.error('Error creating new file:', err)
|
console.error('Error creating new file:', err)
|
||||||
throw err
|
throw err
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
const m = await metadata(path)
|
const m = await stat(path)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
name: path.slice(path.lastIndexOf(sep) + 1),
|
name: path.slice(path.lastIndexOf(sep()) + 1),
|
||||||
path: path,
|
path: path,
|
||||||
entrypointMetadata: m,
|
entrypointMetadata: m,
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
name: PROJECT_ENTRYPOINT,
|
name: PROJECT_ENTRYPOINT,
|
||||||
path: path + sep + PROJECT_ENTRYPOINT,
|
path: await join(path, PROJECT_ENTRYPOINT),
|
||||||
children: [],
|
children: [],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -371,17 +374,17 @@ export async function getUserSettingsFilePath(
|
|||||||
filename: string = SETTINGS_FILE_EXT
|
filename: string = SETTINGS_FILE_EXT
|
||||||
) {
|
) {
|
||||||
const dir = await appConfigDir()
|
const dir = await appConfigDir()
|
||||||
return dir + filename
|
return await join(dir, filename)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function readSettingsFile(
|
export async function readSettingsFile(
|
||||||
path: string
|
path: string
|
||||||
): Promise<Partial<SaveSettingsPayload>> {
|
): Promise<Partial<SaveSettingsPayload>> {
|
||||||
const dir = path.slice(0, path.lastIndexOf(sep))
|
const dir = path.slice(0, path.lastIndexOf(sep()))
|
||||||
|
|
||||||
const dirExists = await exists(dir)
|
const dirExists = await exists(dir)
|
||||||
if (!dirExists) {
|
if (!dirExists) {
|
||||||
await createDir(dir, { recursive: true })
|
await mkdir(dir, { recursive: true })
|
||||||
}
|
}
|
||||||
|
|
||||||
const settingsExist = dirExists ? await exists(path) : false
|
const settingsExist = dirExists ? await exists(path) : false
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { type Metadata } from 'tauri-plugin-fs-extra-api'
|
import { type FileInfo } from '@tauri-apps/plugin-fs'
|
||||||
import { type FileEntry } from '@tauri-apps/api/fs'
|
|
||||||
|
|
||||||
export type IndexLoaderData = {
|
export type IndexLoaderData = {
|
||||||
code: string | null
|
code: string | null
|
||||||
@ -14,12 +13,25 @@ export type FileLoaderData = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export type ProjectWithEntryPointMetadata = FileEntry & {
|
export type ProjectWithEntryPointMetadata = FileEntry & {
|
||||||
entrypointMetadata: Metadata
|
entrypointMetadata: FileInfo
|
||||||
}
|
}
|
||||||
export type HomeLoaderData = {
|
export type HomeLoaderData = {
|
||||||
projects: ProjectWithEntryPointMetadata[]
|
projects: ProjectWithEntryPointMetadata[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// From https://github.com/tauri-apps/tauri/blob/1.x/tooling/api/src/fs.ts#L159
|
||||||
|
// Removed from tauri v2
|
||||||
|
export interface FileEntry {
|
||||||
|
path: string
|
||||||
|
/**
|
||||||
|
* Name of the directory/file
|
||||||
|
* can be null if the path terminates with `..`
|
||||||
|
*/
|
||||||
|
name?: string
|
||||||
|
/** Children of this entry if it's a directory; null otherwise */
|
||||||
|
children?: FileEntry[]
|
||||||
|
}
|
||||||
|
|
||||||
// From the very helpful @jcalz on StackOverflow: https://stackoverflow.com/a/58436959/22753272
|
// From the very helpful @jcalz on StackOverflow: https://stackoverflow.com/a/58436959/22753272
|
||||||
type Join<K, P> = K extends string | number
|
type Join<K, P> = K extends string | number
|
||||||
? P extends string | number
|
? P extends string | number
|
||||||
|
@ -2,7 +2,7 @@ import { createMachine, assign } from 'xstate'
|
|||||||
import { Models } from '@kittycad/lib'
|
import { Models } from '@kittycad/lib'
|
||||||
import withBaseURL from '../lib/withBaseURL'
|
import withBaseURL from '../lib/withBaseURL'
|
||||||
import { isTauri } from 'lib/isTauri'
|
import { isTauri } from 'lib/isTauri'
|
||||||
import { invoke } from '@tauri-apps/api'
|
import { invoke } from '@tauri-apps/api/core'
|
||||||
import { VITE_KC_API_BASE_URL } from 'env'
|
import { VITE_KC_API_BASE_URL } from 'env'
|
||||||
|
|
||||||
const SKIP_AUTH =
|
const SKIP_AUTH =
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { assign, createMachine } from 'xstate'
|
import { assign, createMachine } from 'xstate'
|
||||||
import { type ProjectWithEntryPointMetadata } from 'lib/types'
|
import type { FileEntry, ProjectWithEntryPointMetadata } from 'lib/types'
|
||||||
import { FileEntry } from '@tauri-apps/api/fs'
|
|
||||||
|
|
||||||
export const fileMachine = createMachine(
|
export const fileMachine = createMachine(
|
||||||
{
|
{
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { FormEvent, useEffect } from 'react'
|
import { FormEvent, useEffect } from 'react'
|
||||||
import { removeDir, renameFile } from '@tauri-apps/api/fs'
|
import { remove, rename } from '@tauri-apps/plugin-fs'
|
||||||
import {
|
import {
|
||||||
createNewProject,
|
createNewProject,
|
||||||
getNextProjectIndex,
|
getNextProjectIndex,
|
||||||
@ -31,7 +31,7 @@ import {
|
|||||||
import useStateMachineCommands from '../hooks/useStateMachineCommands'
|
import useStateMachineCommands from '../hooks/useStateMachineCommands'
|
||||||
import { useSettingsAuthContext } from 'hooks/useSettingsAuthContext'
|
import { useSettingsAuthContext } from 'hooks/useSettingsAuthContext'
|
||||||
import { useCommandsContext } from 'hooks/useCommandsContext'
|
import { useCommandsContext } from 'hooks/useCommandsContext'
|
||||||
import { sep } from '@tauri-apps/api/path'
|
import { join, sep } from '@tauri-apps/api/path'
|
||||||
import { homeCommandBarConfig } from 'lib/commandBarConfigs/homeCommandConfig'
|
import { homeCommandBarConfig } from 'lib/commandBarConfigs/homeCommandConfig'
|
||||||
import { useHotkeys } from 'react-hotkeys-hook'
|
import { useHotkeys } from 'react-hotkeys-hook'
|
||||||
import { isTauri } from 'lib/isTauri'
|
import { isTauri } from 'lib/isTauri'
|
||||||
@ -76,7 +76,7 @@ const Home = () => {
|
|||||||
event: EventFrom<typeof homeMachine>
|
event: EventFrom<typeof homeMachine>
|
||||||
) => {
|
) => {
|
||||||
if (event.data && 'name' in event.data) {
|
if (event.data && 'name' in event.data) {
|
||||||
let projectPath = context.defaultDirectory + sep + event.data.name
|
let projectPath = context.defaultDirectory + sep() + event.data.name
|
||||||
onProjectOpen(
|
onProjectOpen(
|
||||||
{
|
{
|
||||||
name: event.data.name,
|
name: event.data.name,
|
||||||
@ -109,7 +109,7 @@ const Home = () => {
|
|||||||
name = interpolateProjectNameWithIndex(name, nextIndex)
|
name = interpolateProjectNameWithIndex(name, nextIndex)
|
||||||
}
|
}
|
||||||
|
|
||||||
await createNewProject(context.defaultDirectory + sep + name)
|
await createNewProject(await join(context.defaultDirectory, name))
|
||||||
|
|
||||||
return `Successfully created "${name}"`
|
return `Successfully created "${name}"`
|
||||||
},
|
},
|
||||||
@ -124,9 +124,10 @@ const Home = () => {
|
|||||||
name = interpolateProjectNameWithIndex(name, nextIndex)
|
name = interpolateProjectNameWithIndex(name, nextIndex)
|
||||||
}
|
}
|
||||||
|
|
||||||
await renameFile(
|
await rename(
|
||||||
context.defaultDirectory + sep + oldName,
|
await join(context.defaultDirectory, oldName),
|
||||||
context.defaultDirectory + sep + name
|
await join(context.defaultDirectory, name),
|
||||||
|
{}
|
||||||
)
|
)
|
||||||
return `Successfully renamed "${oldName}" to "${name}"`
|
return `Successfully renamed "${oldName}" to "${name}"`
|
||||||
},
|
},
|
||||||
@ -134,7 +135,7 @@ const Home = () => {
|
|||||||
context: ContextFrom<typeof homeMachine>,
|
context: ContextFrom<typeof homeMachine>,
|
||||||
event: EventFrom<typeof homeMachine, 'Delete project'>
|
event: EventFrom<typeof homeMachine, 'Delete project'>
|
||||||
) => {
|
) => {
|
||||||
await removeDir(context.defaultDirectory + sep + event.data.name, {
|
await remove(await join(context.defaultDirectory, event.data.name), {
|
||||||
recursive: true,
|
recursive: true,
|
||||||
})
|
})
|
||||||
return `Successfully deleted "${event.data.name}"`
|
return `Successfully deleted "${event.data.name}"`
|
||||||
|
@ -22,7 +22,7 @@ export default function CmdK() {
|
|||||||
<h2 className="text-2xl font-bold">Command Bar</h2>
|
<h2 className="text-2xl font-bold">Command Bar</h2>
|
||||||
<p className="my-4">
|
<p className="my-4">
|
||||||
Press{' '}
|
Press{' '}
|
||||||
{platformName === 'darwin' ? (
|
{platformName === 'macos' ? (
|
||||||
<>
|
<>
|
||||||
<kbd className={kbdClasses}>⌘K</kbd>
|
<kbd className={kbdClasses}>⌘K</kbd>
|
||||||
</>
|
</>
|
||||||
|
@ -19,7 +19,7 @@ import { useNavigate } from 'react-router-dom'
|
|||||||
import { paths } from 'lib/paths'
|
import { paths } from 'lib/paths'
|
||||||
import { useEffect } from 'react'
|
import { useEffect } from 'react'
|
||||||
import { kclManager } from 'lib/singletons'
|
import { kclManager } from 'lib/singletons'
|
||||||
import { sep } from '@tauri-apps/api/path'
|
import { join } from '@tauri-apps/api/path'
|
||||||
import { APP_NAME, PROJECT_ENTRYPOINT } from 'lib/constants'
|
import { APP_NAME, PROJECT_ENTRYPOINT } from 'lib/constants'
|
||||||
|
|
||||||
function OnboardingWithNewFile() {
|
function OnboardingWithNewFile() {
|
||||||
@ -45,12 +45,12 @@ function OnboardingWithNewFile() {
|
|||||||
nextIndex
|
nextIndex
|
||||||
)
|
)
|
||||||
const newFile = await createNewProject(
|
const newFile = await createNewProject(
|
||||||
projectDirectory.current + sep + name,
|
await join(projectDirectory.current, name),
|
||||||
bracket
|
bracket
|
||||||
)
|
)
|
||||||
navigate(
|
navigate(
|
||||||
`${paths.FILE}/${encodeURIComponent(
|
`${paths.FILE}/${encodeURIComponent(
|
||||||
newFile.path + sep + PROJECT_ENTRYPOINT
|
await join(newFile.path, PROJECT_ENTRYPOINT)
|
||||||
)}${paths.ONBOARDING.INDEX}`
|
)}${paths.ONBOARDING.INDEX}`
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -19,11 +19,11 @@ import {
|
|||||||
interpolateProjectNameWithIndex,
|
interpolateProjectNameWithIndex,
|
||||||
} from 'lib/tauriFS'
|
} from 'lib/tauriFS'
|
||||||
import { ONBOARDING_PROJECT_NAME } from './Onboarding'
|
import { ONBOARDING_PROJECT_NAME } from './Onboarding'
|
||||||
import { sep } from '@tauri-apps/api/path'
|
import { join, sep } from '@tauri-apps/api/path'
|
||||||
import { bracket } from 'lib/exampleKcl'
|
import { bracket } from 'lib/exampleKcl'
|
||||||
import { isTauri } from 'lib/isTauri'
|
import { isTauri } from 'lib/isTauri'
|
||||||
import { invoke } from '@tauri-apps/api'
|
|
||||||
import toast from 'react-hot-toast'
|
import toast from 'react-hot-toast'
|
||||||
|
import { invoke } from '@tauri-apps/api/core'
|
||||||
import React, { Fragment, useMemo, useRef, useState } from 'react'
|
import React, { Fragment, useMemo, useRef, useState } from 'react'
|
||||||
import { Setting } from 'lib/settings/initialSettings'
|
import { Setting } from 'lib/settings/initialSettings'
|
||||||
import decamelize from 'decamelize'
|
import decamelize from 'decamelize'
|
||||||
@ -49,7 +49,7 @@ export const Settings = () => {
|
|||||||
location.pathname
|
location.pathname
|
||||||
.replace(paths.FILE + '/', '')
|
.replace(paths.FILE + '/', '')
|
||||||
.replace(paths.SETTINGS, '')
|
.replace(paths.SETTINGS, '')
|
||||||
.slice(0, decodeURI(location.pathname).lastIndexOf(sep))
|
.slice(0, decodeURI(location.pathname).lastIndexOf(sep()))
|
||||||
)
|
)
|
||||||
: undefined
|
: undefined
|
||||||
const [settingsLevel, setSettingsLevel] = useState<SettingsLevel>(
|
const [settingsLevel, setSettingsLevel] = useState<SettingsLevel>(
|
||||||
@ -90,7 +90,7 @@ export const Settings = () => {
|
|||||||
nextIndex
|
nextIndex
|
||||||
)
|
)
|
||||||
const newFile = await createNewProject(
|
const newFile = await createNewProject(
|
||||||
defaultDirectory + sep + name,
|
await join(defaultDirectory, name),
|
||||||
bracket
|
bracket
|
||||||
)
|
)
|
||||||
navigate(`${paths.FILE}/${encodeURIComponent(newFile.path)}`)
|
navigate(`${paths.FILE}/${encodeURIComponent(newFile.path)}`)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { ActionButton } from '../components/ActionButton'
|
import { ActionButton } from '../components/ActionButton'
|
||||||
import { isTauri } from '../lib/isTauri'
|
import { isTauri } from '../lib/isTauri'
|
||||||
import { invoke } from '@tauri-apps/api/tauri'
|
import { invoke } from '@tauri-apps/api/core'
|
||||||
import { VITE_KC_SITE_BASE_URL, VITE_KC_API_BASE_URL } from '../env'
|
import { VITE_KC_SITE_BASE_URL, VITE_KC_API_BASE_URL } from '../env'
|
||||||
import { Themes, getSystemTheme } from '../lib/theme'
|
import { Themes, getSystemTheme } from '../lib/theme'
|
||||||
import { paths } from 'lib/paths'
|
import { paths } from 'lib/paths'
|
||||||
|
25
src/wasm-lib/Cargo.lock
generated
@ -927,7 +927,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "derive-docs"
|
name = "derive-docs"
|
||||||
version = "0.1.12"
|
version = "0.1.13"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"Inflector",
|
"Inflector",
|
||||||
"anyhow",
|
"anyhow",
|
||||||
@ -944,23 +944,6 @@ dependencies = [
|
|||||||
"syn 2.0.58",
|
"syn 2.0.58",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "derive-docs"
|
|
||||||
version = "0.1.12"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "138b94245509a9dd516008788b585c34847829cf37b40a758b4aa581cf94f147"
|
|
||||||
dependencies = [
|
|
||||||
"Inflector",
|
|
||||||
"convert_case",
|
|
||||||
"once_cell",
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"regex",
|
|
||||||
"serde",
|
|
||||||
"serde_tokenstream",
|
|
||||||
"syn 2.0.58",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "diesel_derives"
|
name = "diesel_derives"
|
||||||
version = "2.1.3"
|
version = "2.1.3"
|
||||||
@ -1460,9 +1443,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "h2"
|
name = "h2"
|
||||||
version = "0.3.25"
|
version = "0.3.26"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4fbd2820c5e49886948654ab546d0688ff24530286bdcf8fca3cefb16d4618eb"
|
checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"fnv",
|
"fnv",
|
||||||
@ -1879,7 +1862,7 @@ dependencies = [
|
|||||||
"criterion",
|
"criterion",
|
||||||
"dashmap",
|
"dashmap",
|
||||||
"databake",
|
"databake",
|
||||||
"derive-docs 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
"derive-docs",
|
||||||
"expectorate",
|
"expectorate",
|
||||||
"futures",
|
"futures",
|
||||||
"gltf-json",
|
"gltf-json",
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "derive-docs"
|
name = "derive-docs"
|
||||||
description = "A tool for generating documentation from Rust derive macros"
|
description = "A tool for generating documentation from Rust derive macros"
|
||||||
version = "0.1.12"
|
version = "0.1.13"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
repository = "https://github.com/KittyCAD/modeling-app"
|
repository = "https://github.com/KittyCAD/modeling-app"
|
||||||
|
@ -793,7 +793,6 @@ fn generate_code_block_test(
|
|||||||
|
|
||||||
ctx.engine
|
ctx.engine
|
||||||
.send_modeling_cmd(
|
.send_modeling_cmd(
|
||||||
false,
|
|
||||||
uuid::Uuid::new_v4(),
|
uuid::Uuid::new_v4(),
|
||||||
crate::executor::SourceRange::default(),
|
crate::executor::SourceRange::default(),
|
||||||
kittycad::types::ModelingCmd::DefaultCameraLookAt {
|
kittycad::types::ModelingCmd::DefaultCameraLookAt {
|
||||||
@ -809,7 +808,6 @@ fn generate_code_block_test(
|
|||||||
let resp = ctx
|
let resp = ctx
|
||||||
.engine
|
.engine
|
||||||
.send_modeling_cmd(
|
.send_modeling_cmd(
|
||||||
false,
|
|
||||||
uuid::Uuid::new_v4(),
|
uuid::Uuid::new_v4(),
|
||||||
crate::executor::SourceRange::default(),
|
crate::executor::SourceRange::default(),
|
||||||
kittycad::types::ModelingCmd::TakeSnapshot {
|
kittycad::types::ModelingCmd::TakeSnapshot {
|
||||||
|
@ -39,7 +39,6 @@ mod test_examples_show {
|
|||||||
let (x, y) = crate::std::utils::get_camera_zoom_magnitude_per_unit_length(units);
|
let (x, y) = crate::std::utils::get_camera_zoom_magnitude_per_unit_length(units);
|
||||||
ctx.engine
|
ctx.engine
|
||||||
.send_modeling_cmd(
|
.send_modeling_cmd(
|
||||||
false,
|
|
||||||
uuid::Uuid::new_v4(),
|
uuid::Uuid::new_v4(),
|
||||||
crate::executor::SourceRange::default(),
|
crate::executor::SourceRange::default(),
|
||||||
kittycad::types::ModelingCmd::DefaultCameraLookAt {
|
kittycad::types::ModelingCmd::DefaultCameraLookAt {
|
||||||
@ -66,7 +65,6 @@ mod test_examples_show {
|
|||||||
let resp = ctx
|
let resp = ctx
|
||||||
.engine
|
.engine
|
||||||
.send_modeling_cmd(
|
.send_modeling_cmd(
|
||||||
false,
|
|
||||||
uuid::Uuid::new_v4(),
|
uuid::Uuid::new_v4(),
|
||||||
crate::executor::SourceRange::default(),
|
crate::executor::SourceRange::default(),
|
||||||
kittycad::types::ModelingCmd::TakeSnapshot {
|
kittycad::types::ModelingCmd::TakeSnapshot {
|
||||||
@ -136,7 +134,6 @@ mod test_examples_show {
|
|||||||
let (x, y) = crate::std::utils::get_camera_zoom_magnitude_per_unit_length(units);
|
let (x, y) = crate::std::utils::get_camera_zoom_magnitude_per_unit_length(units);
|
||||||
ctx.engine
|
ctx.engine
|
||||||
.send_modeling_cmd(
|
.send_modeling_cmd(
|
||||||
false,
|
|
||||||
uuid::Uuid::new_v4(),
|
uuid::Uuid::new_v4(),
|
||||||
crate::executor::SourceRange::default(),
|
crate::executor::SourceRange::default(),
|
||||||
kittycad::types::ModelingCmd::DefaultCameraLookAt {
|
kittycad::types::ModelingCmd::DefaultCameraLookAt {
|
||||||
@ -163,7 +160,6 @@ mod test_examples_show {
|
|||||||
let resp = ctx
|
let resp = ctx
|
||||||
.engine
|
.engine
|
||||||
.send_modeling_cmd(
|
.send_modeling_cmd(
|
||||||
false,
|
|
||||||
uuid::Uuid::new_v4(),
|
uuid::Uuid::new_v4(),
|
||||||
crate::executor::SourceRange::default(),
|
crate::executor::SourceRange::default(),
|
||||||
kittycad::types::ModelingCmd::TakeSnapshot {
|
kittycad::types::ModelingCmd::TakeSnapshot {
|
||||||
|
@ -39,7 +39,6 @@ mod test_examples_show {
|
|||||||
let (x, y) = crate::std::utils::get_camera_zoom_magnitude_per_unit_length(units);
|
let (x, y) = crate::std::utils::get_camera_zoom_magnitude_per_unit_length(units);
|
||||||
ctx.engine
|
ctx.engine
|
||||||
.send_modeling_cmd(
|
.send_modeling_cmd(
|
||||||
false,
|
|
||||||
uuid::Uuid::new_v4(),
|
uuid::Uuid::new_v4(),
|
||||||
crate::executor::SourceRange::default(),
|
crate::executor::SourceRange::default(),
|
||||||
kittycad::types::ModelingCmd::DefaultCameraLookAt {
|
kittycad::types::ModelingCmd::DefaultCameraLookAt {
|
||||||
@ -66,7 +65,6 @@ mod test_examples_show {
|
|||||||
let resp = ctx
|
let resp = ctx
|
||||||
.engine
|
.engine
|
||||||
.send_modeling_cmd(
|
.send_modeling_cmd(
|
||||||
false,
|
|
||||||
uuid::Uuid::new_v4(),
|
uuid::Uuid::new_v4(),
|
||||||
crate::executor::SourceRange::default(),
|
crate::executor::SourceRange::default(),
|
||||||
kittycad::types::ModelingCmd::TakeSnapshot {
|
kittycad::types::ModelingCmd::TakeSnapshot {
|
||||||
|
@ -39,7 +39,6 @@ mod test_examples_my_func {
|
|||||||
let (x, y) = crate::std::utils::get_camera_zoom_magnitude_per_unit_length(units);
|
let (x, y) = crate::std::utils::get_camera_zoom_magnitude_per_unit_length(units);
|
||||||
ctx.engine
|
ctx.engine
|
||||||
.send_modeling_cmd(
|
.send_modeling_cmd(
|
||||||
false,
|
|
||||||
uuid::Uuid::new_v4(),
|
uuid::Uuid::new_v4(),
|
||||||
crate::executor::SourceRange::default(),
|
crate::executor::SourceRange::default(),
|
||||||
kittycad::types::ModelingCmd::DefaultCameraLookAt {
|
kittycad::types::ModelingCmd::DefaultCameraLookAt {
|
||||||
@ -66,7 +65,6 @@ mod test_examples_my_func {
|
|||||||
let resp = ctx
|
let resp = ctx
|
||||||
.engine
|
.engine
|
||||||
.send_modeling_cmd(
|
.send_modeling_cmd(
|
||||||
false,
|
|
||||||
uuid::Uuid::new_v4(),
|
uuid::Uuid::new_v4(),
|
||||||
crate::executor::SourceRange::default(),
|
crate::executor::SourceRange::default(),
|
||||||
kittycad::types::ModelingCmd::TakeSnapshot {
|
kittycad::types::ModelingCmd::TakeSnapshot {
|
||||||
@ -136,7 +134,6 @@ mod test_examples_my_func {
|
|||||||
let (x, y) = crate::std::utils::get_camera_zoom_magnitude_per_unit_length(units);
|
let (x, y) = crate::std::utils::get_camera_zoom_magnitude_per_unit_length(units);
|
||||||
ctx.engine
|
ctx.engine
|
||||||
.send_modeling_cmd(
|
.send_modeling_cmd(
|
||||||
false,
|
|
||||||
uuid::Uuid::new_v4(),
|
uuid::Uuid::new_v4(),
|
||||||
crate::executor::SourceRange::default(),
|
crate::executor::SourceRange::default(),
|
||||||
kittycad::types::ModelingCmd::DefaultCameraLookAt {
|
kittycad::types::ModelingCmd::DefaultCameraLookAt {
|
||||||
@ -163,7 +160,6 @@ mod test_examples_my_func {
|
|||||||
let resp = ctx
|
let resp = ctx
|
||||||
.engine
|
.engine
|
||||||
.send_modeling_cmd(
|
.send_modeling_cmd(
|
||||||
false,
|
|
||||||
uuid::Uuid::new_v4(),
|
uuid::Uuid::new_v4(),
|
||||||
crate::executor::SourceRange::default(),
|
crate::executor::SourceRange::default(),
|
||||||
kittycad::types::ModelingCmd::TakeSnapshot {
|
kittycad::types::ModelingCmd::TakeSnapshot {
|
||||||
|
@ -40,7 +40,6 @@ mod test_examples_import {
|
|||||||
let (x, y) = crate::std::utils::get_camera_zoom_magnitude_per_unit_length(units);
|
let (x, y) = crate::std::utils::get_camera_zoom_magnitude_per_unit_length(units);
|
||||||
ctx.engine
|
ctx.engine
|
||||||
.send_modeling_cmd(
|
.send_modeling_cmd(
|
||||||
false,
|
|
||||||
uuid::Uuid::new_v4(),
|
uuid::Uuid::new_v4(),
|
||||||
crate::executor::SourceRange::default(),
|
crate::executor::SourceRange::default(),
|
||||||
kittycad::types::ModelingCmd::DefaultCameraLookAt {
|
kittycad::types::ModelingCmd::DefaultCameraLookAt {
|
||||||
@ -67,7 +66,6 @@ mod test_examples_import {
|
|||||||
let resp = ctx
|
let resp = ctx
|
||||||
.engine
|
.engine
|
||||||
.send_modeling_cmd(
|
.send_modeling_cmd(
|
||||||
false,
|
|
||||||
uuid::Uuid::new_v4(),
|
uuid::Uuid::new_v4(),
|
||||||
crate::executor::SourceRange::default(),
|
crate::executor::SourceRange::default(),
|
||||||
kittycad::types::ModelingCmd::TakeSnapshot {
|
kittycad::types::ModelingCmd::TakeSnapshot {
|
||||||
@ -138,7 +136,6 @@ mod test_examples_import {
|
|||||||
let (x, y) = crate::std::utils::get_camera_zoom_magnitude_per_unit_length(units);
|
let (x, y) = crate::std::utils::get_camera_zoom_magnitude_per_unit_length(units);
|
||||||
ctx.engine
|
ctx.engine
|
||||||
.send_modeling_cmd(
|
.send_modeling_cmd(
|
||||||
false,
|
|
||||||
uuid::Uuid::new_v4(),
|
uuid::Uuid::new_v4(),
|
||||||
crate::executor::SourceRange::default(),
|
crate::executor::SourceRange::default(),
|
||||||
kittycad::types::ModelingCmd::DefaultCameraLookAt {
|
kittycad::types::ModelingCmd::DefaultCameraLookAt {
|
||||||
@ -165,7 +162,6 @@ mod test_examples_import {
|
|||||||
let resp = ctx
|
let resp = ctx
|
||||||
.engine
|
.engine
|
||||||
.send_modeling_cmd(
|
.send_modeling_cmd(
|
||||||
false,
|
|
||||||
uuid::Uuid::new_v4(),
|
uuid::Uuid::new_v4(),
|
||||||
crate::executor::SourceRange::default(),
|
crate::executor::SourceRange::default(),
|
||||||
kittycad::types::ModelingCmd::TakeSnapshot {
|
kittycad::types::ModelingCmd::TakeSnapshot {
|
||||||
|
@ -39,7 +39,6 @@ mod test_examples_line_to {
|
|||||||
let (x, y) = crate::std::utils::get_camera_zoom_magnitude_per_unit_length(units);
|
let (x, y) = crate::std::utils::get_camera_zoom_magnitude_per_unit_length(units);
|
||||||
ctx.engine
|
ctx.engine
|
||||||
.send_modeling_cmd(
|
.send_modeling_cmd(
|
||||||
false,
|
|
||||||
uuid::Uuid::new_v4(),
|
uuid::Uuid::new_v4(),
|
||||||
crate::executor::SourceRange::default(),
|
crate::executor::SourceRange::default(),
|
||||||
kittycad::types::ModelingCmd::DefaultCameraLookAt {
|
kittycad::types::ModelingCmd::DefaultCameraLookAt {
|
||||||
@ -66,7 +65,6 @@ mod test_examples_line_to {
|
|||||||
let resp = ctx
|
let resp = ctx
|
||||||
.engine
|
.engine
|
||||||
.send_modeling_cmd(
|
.send_modeling_cmd(
|
||||||
false,
|
|
||||||
uuid::Uuid::new_v4(),
|
uuid::Uuid::new_v4(),
|
||||||
crate::executor::SourceRange::default(),
|
crate::executor::SourceRange::default(),
|
||||||
kittycad::types::ModelingCmd::TakeSnapshot {
|
kittycad::types::ModelingCmd::TakeSnapshot {
|
||||||
@ -136,7 +134,6 @@ mod test_examples_line_to {
|
|||||||
let (x, y) = crate::std::utils::get_camera_zoom_magnitude_per_unit_length(units);
|
let (x, y) = crate::std::utils::get_camera_zoom_magnitude_per_unit_length(units);
|
||||||
ctx.engine
|
ctx.engine
|
||||||
.send_modeling_cmd(
|
.send_modeling_cmd(
|
||||||
false,
|
|
||||||
uuid::Uuid::new_v4(),
|
uuid::Uuid::new_v4(),
|
||||||
crate::executor::SourceRange::default(),
|
crate::executor::SourceRange::default(),
|
||||||
kittycad::types::ModelingCmd::DefaultCameraLookAt {
|
kittycad::types::ModelingCmd::DefaultCameraLookAt {
|
||||||
@ -163,7 +160,6 @@ mod test_examples_line_to {
|
|||||||
let resp = ctx
|
let resp = ctx
|
||||||
.engine
|
.engine
|
||||||
.send_modeling_cmd(
|
.send_modeling_cmd(
|
||||||
false,
|
|
||||||
uuid::Uuid::new_v4(),
|
uuid::Uuid::new_v4(),
|
||||||
crate::executor::SourceRange::default(),
|
crate::executor::SourceRange::default(),
|
||||||
kittycad::types::ModelingCmd::TakeSnapshot {
|
kittycad::types::ModelingCmd::TakeSnapshot {
|
||||||
|
@ -39,7 +39,6 @@ mod test_examples_min {
|
|||||||
let (x, y) = crate::std::utils::get_camera_zoom_magnitude_per_unit_length(units);
|
let (x, y) = crate::std::utils::get_camera_zoom_magnitude_per_unit_length(units);
|
||||||
ctx.engine
|
ctx.engine
|
||||||
.send_modeling_cmd(
|
.send_modeling_cmd(
|
||||||
false,
|
|
||||||
uuid::Uuid::new_v4(),
|
uuid::Uuid::new_v4(),
|
||||||
crate::executor::SourceRange::default(),
|
crate::executor::SourceRange::default(),
|
||||||
kittycad::types::ModelingCmd::DefaultCameraLookAt {
|
kittycad::types::ModelingCmd::DefaultCameraLookAt {
|
||||||
@ -66,7 +65,6 @@ mod test_examples_min {
|
|||||||
let resp = ctx
|
let resp = ctx
|
||||||
.engine
|
.engine
|
||||||
.send_modeling_cmd(
|
.send_modeling_cmd(
|
||||||
false,
|
|
||||||
uuid::Uuid::new_v4(),
|
uuid::Uuid::new_v4(),
|
||||||
crate::executor::SourceRange::default(),
|
crate::executor::SourceRange::default(),
|
||||||
kittycad::types::ModelingCmd::TakeSnapshot {
|
kittycad::types::ModelingCmd::TakeSnapshot {
|
||||||
@ -136,7 +134,6 @@ mod test_examples_min {
|
|||||||
let (x, y) = crate::std::utils::get_camera_zoom_magnitude_per_unit_length(units);
|
let (x, y) = crate::std::utils::get_camera_zoom_magnitude_per_unit_length(units);
|
||||||
ctx.engine
|
ctx.engine
|
||||||
.send_modeling_cmd(
|
.send_modeling_cmd(
|
||||||
false,
|
|
||||||
uuid::Uuid::new_v4(),
|
uuid::Uuid::new_v4(),
|
||||||
crate::executor::SourceRange::default(),
|
crate::executor::SourceRange::default(),
|
||||||
kittycad::types::ModelingCmd::DefaultCameraLookAt {
|
kittycad::types::ModelingCmd::DefaultCameraLookAt {
|
||||||
@ -163,7 +160,6 @@ mod test_examples_min {
|
|||||||
let resp = ctx
|
let resp = ctx
|
||||||
.engine
|
.engine
|
||||||
.send_modeling_cmd(
|
.send_modeling_cmd(
|
||||||
false,
|
|
||||||
uuid::Uuid::new_v4(),
|
uuid::Uuid::new_v4(),
|
||||||
crate::executor::SourceRange::default(),
|
crate::executor::SourceRange::default(),
|
||||||
kittycad::types::ModelingCmd::TakeSnapshot {
|
kittycad::types::ModelingCmd::TakeSnapshot {
|
||||||
|
@ -39,7 +39,6 @@ mod test_examples_show {
|
|||||||
let (x, y) = crate::std::utils::get_camera_zoom_magnitude_per_unit_length(units);
|
let (x, y) = crate::std::utils::get_camera_zoom_magnitude_per_unit_length(units);
|
||||||
ctx.engine
|
ctx.engine
|
||||||
.send_modeling_cmd(
|
.send_modeling_cmd(
|
||||||
false,
|
|
||||||
uuid::Uuid::new_v4(),
|
uuid::Uuid::new_v4(),
|
||||||
crate::executor::SourceRange::default(),
|
crate::executor::SourceRange::default(),
|
||||||
kittycad::types::ModelingCmd::DefaultCameraLookAt {
|
kittycad::types::ModelingCmd::DefaultCameraLookAt {
|
||||||
@ -66,7 +65,6 @@ mod test_examples_show {
|
|||||||
let resp = ctx
|
let resp = ctx
|
||||||
.engine
|
.engine
|
||||||
.send_modeling_cmd(
|
.send_modeling_cmd(
|
||||||
false,
|
|
||||||
uuid::Uuid::new_v4(),
|
uuid::Uuid::new_v4(),
|
||||||
crate::executor::SourceRange::default(),
|
crate::executor::SourceRange::default(),
|
||||||
kittycad::types::ModelingCmd::TakeSnapshot {
|
kittycad::types::ModelingCmd::TakeSnapshot {
|
||||||
|
@ -39,7 +39,6 @@ mod test_examples_import {
|
|||||||
let (x, y) = crate::std::utils::get_camera_zoom_magnitude_per_unit_length(units);
|
let (x, y) = crate::std::utils::get_camera_zoom_magnitude_per_unit_length(units);
|
||||||
ctx.engine
|
ctx.engine
|
||||||
.send_modeling_cmd(
|
.send_modeling_cmd(
|
||||||
false,
|
|
||||||
uuid::Uuid::new_v4(),
|
uuid::Uuid::new_v4(),
|
||||||
crate::executor::SourceRange::default(),
|
crate::executor::SourceRange::default(),
|
||||||
kittycad::types::ModelingCmd::DefaultCameraLookAt {
|
kittycad::types::ModelingCmd::DefaultCameraLookAt {
|
||||||
@ -66,7 +65,6 @@ mod test_examples_import {
|
|||||||
let resp = ctx
|
let resp = ctx
|
||||||
.engine
|
.engine
|
||||||
.send_modeling_cmd(
|
.send_modeling_cmd(
|
||||||
false,
|
|
||||||
uuid::Uuid::new_v4(),
|
uuid::Uuid::new_v4(),
|
||||||
crate::executor::SourceRange::default(),
|
crate::executor::SourceRange::default(),
|
||||||
kittycad::types::ModelingCmd::TakeSnapshot {
|
kittycad::types::ModelingCmd::TakeSnapshot {
|
||||||
|