Franknoirot/file tree fixes (#2525)
* Navigate between files with single-click * Better semantic name for optional event passed into FileTree * Bug fix: reset modeling state when navigating to a new file * Add more context to E2E test TODO comment * Newly-created file tree items are immediately set to renaming mode * Bug fix: redirect to working file if you delete your current one * Remove ContextMenu, unrelated branch * Turn off autocorrect in renaming form * Gracefully handle renaming a folder that our current file is inside of * Update cargo.lock * Fix renaming queue * Navigate to newly-created files * Make delete project and delete file/folder share deletion confirmation component * Bug fix: navigate to project root if we delete our current file's parent directory * Don't navigate to newly-created directories
This commit is contained in:
@ -3576,6 +3576,10 @@ test('Basic default modeling and sketch hotkeys work', async ({ page }) => {
|
|||||||
* TODO: There is a bug somewhere that causes this test to fail
|
* TODO: There is a bug somewhere that causes this test to fail
|
||||||
* if you toggle the codePane closed before your trigger the
|
* if you toggle the codePane closed before your trigger the
|
||||||
* start of the sketch.
|
* start of the sketch.
|
||||||
|
* and a separate Safari-only bug that causes the test to fail
|
||||||
|
* if the pane is open the entire test. The maintainer of CodeMirror
|
||||||
|
* has pinpointed this to the unusual browser behavior:
|
||||||
|
* https://discuss.codemirror.net/t/how-to-force-unfocus-of-the-codemirror-element-in-safari/8095/3
|
||||||
*/
|
*/
|
||||||
await codePaneButton.click()
|
await codePaneButton.click()
|
||||||
|
|
||||||
|
196
src-tauri/Cargo.lock
generated
196
src-tauri/Cargo.lock
generated
@ -344,7 +344,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.65",
|
"syn 2.0.66",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -379,7 +379,7 @@ checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.65",
|
"syn 2.0.66",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -425,7 +425,7 @@ checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.65",
|
"syn 2.0.66",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -574,7 +574,7 @@ dependencies = [
|
|||||||
"proc-macro-crate 3.1.0",
|
"proc-macro-crate 3.1.0",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.65",
|
"syn 2.0.66",
|
||||||
"syn_derive",
|
"syn_derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -883,7 +883,7 @@ dependencies = [
|
|||||||
"heck 0.5.0",
|
"heck 0.5.0",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.65",
|
"syn 2.0.66",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1085,7 +1085,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331"
|
checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.65",
|
"syn 2.0.66",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1095,7 +1095,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "edb49164822f3ee45b17acd4a208cfc1251410cf0cad9a833234c9890774dd9f"
|
checksum = "edb49164822f3ee45b17acd4a208cfc1251410cf0cad9a833234c9890774dd9f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.65",
|
"syn 2.0.66",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1119,7 +1119,7 @@ dependencies = [
|
|||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"strsim 0.10.0",
|
"strsim 0.10.0",
|
||||||
"syn 2.0.65",
|
"syn 2.0.66",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1130,7 +1130,7 @@ checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"darling_core",
|
"darling_core",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.65",
|
"syn 2.0.66",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1177,7 +1177,7 @@ checksum = "377af281d8f23663862a7c84623bc5dcf7f8c44b13c7496a590bdc157f941a43"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.65",
|
"syn 2.0.66",
|
||||||
"synstructure",
|
"synstructure",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -1214,7 +1214,7 @@ dependencies = [
|
|||||||
"regex",
|
"regex",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_tokenstream",
|
"serde_tokenstream",
|
||||||
"syn 2.0.65",
|
"syn 2.0.66",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1225,7 +1225,7 @@ checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.65",
|
"syn 2.0.66",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1287,7 +1287,7 @@ checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.65",
|
"syn 2.0.66",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1319,7 +1319,7 @@ checksum = "f2b99bf03862d7f545ebc28ddd33a665b50865f4dfd84031a393823879bd4c54"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.65",
|
"syn 2.0.66",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1417,7 +1417,7 @@ checksum = "5c785274071b1b420972453b306eeca06acf4633829db4223b58a2a8c5953bc4"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.65",
|
"syn 2.0.66",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1568,7 +1568,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.65",
|
"syn 2.0.66",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1684,7 +1684,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.65",
|
"syn 2.0.66",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1960,7 +1960,7 @@ dependencies = [
|
|||||||
"proc-macro-error",
|
"proc-macro-error",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.65",
|
"syn 2.0.66",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1988,7 +1988,7 @@ dependencies = [
|
|||||||
"inflections",
|
"inflections",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.65",
|
"syn 2.0.66",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -2063,7 +2063,7 @@ dependencies = [
|
|||||||
"proc-macro-error",
|
"proc-macro-error",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.65",
|
"syn 2.0.66",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -2461,15 +2461,6 @@ dependencies = [
|
|||||||
"once_cell",
|
"once_cell",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "itertools"
|
|
||||||
version = "0.10.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
|
|
||||||
dependencies = [
|
|
||||||
"either",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itertools"
|
name = "itertools"
|
||||||
version = "0.12.1"
|
version = "0.12.1"
|
||||||
@ -2568,7 +2559,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kcl-lib"
|
name = "kcl-lib"
|
||||||
version = "0.1.57"
|
version = "0.1.58"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"approx",
|
"approx",
|
||||||
@ -2591,7 +2582,7 @@ dependencies = [
|
|||||||
"kittycad-execution-plan-traits",
|
"kittycad-execution-plan-traits",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"mime_guess",
|
"mime_guess",
|
||||||
"parse-display 0.9.0",
|
"parse-display",
|
||||||
"reqwest 0.11.27",
|
"reqwest 0.11.27",
|
||||||
"ropey",
|
"ropey",
|
||||||
"schemars",
|
"schemars",
|
||||||
@ -2627,13 +2618,13 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kittycad"
|
name = "kittycad"
|
||||||
version = "0.3.1"
|
version = "0.3.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2c6e12eb45fd9a28c8e99dbdef54556246b39acee14e4aa6f0fc43636caa62d9"
|
checksum = "b0cbef813153197e60c0e96f59eea0b75f8418380f414b20250ee81b60e522c3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"base64 0.21.7",
|
"base64 0.22.1",
|
||||||
"bigdecimal",
|
"bigdecimal",
|
||||||
"bytes",
|
"bytes",
|
||||||
"chrono",
|
"chrono",
|
||||||
@ -2642,10 +2633,10 @@ dependencies = [
|
|||||||
"format_serde_error",
|
"format_serde_error",
|
||||||
"futures",
|
"futures",
|
||||||
"http 0.2.12",
|
"http 0.2.12",
|
||||||
"itertools 0.10.5",
|
"itertools",
|
||||||
"log",
|
"log",
|
||||||
"mime_guess",
|
"mime_guess",
|
||||||
"parse-display 0.8.2",
|
"parse-display",
|
||||||
"phonenumber",
|
"phonenumber",
|
||||||
"rand 0.8.5",
|
"rand 0.8.5",
|
||||||
"reqwest 0.11.27",
|
"reqwest 0.11.27",
|
||||||
@ -2672,7 +2663,7 @@ checksum = "0611fc9b9786175da21d895ffa0f65039e19c9111e94a41b7af999e3b95f045f"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.65",
|
"syn 2.0.66",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -3360,43 +3351,17 @@ dependencies = [
|
|||||||
"windows-targets 0.48.5",
|
"windows-targets 0.48.5",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "parse-display"
|
|
||||||
version = "0.8.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "c6509d08722b53e8dafe97f2027b22ccbe3a5db83cb352931e9716b0aa44bc5c"
|
|
||||||
dependencies = [
|
|
||||||
"once_cell",
|
|
||||||
"parse-display-derive 0.8.2",
|
|
||||||
"regex",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "parse-display"
|
name = "parse-display"
|
||||||
version = "0.9.0"
|
version = "0.9.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "06af5f9333eb47bd9ba8462d612e37a8328a5cb80b13f0af4de4c3b89f52dee5"
|
checksum = "06af5f9333eb47bd9ba8462d612e37a8328a5cb80b13f0af4de4c3b89f52dee5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"parse-display-derive 0.9.0",
|
"parse-display-derive",
|
||||||
"regex",
|
"regex",
|
||||||
"regex-syntax 0.8.3",
|
"regex-syntax 0.8.3",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "parse-display-derive"
|
|
||||||
version = "0.8.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "68517892c8daf78da08c0db777fcc17e07f2f63ef70041718f8a7630ad84f341"
|
|
||||||
dependencies = [
|
|
||||||
"once_cell",
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"regex",
|
|
||||||
"regex-syntax 0.7.5",
|
|
||||||
"structmeta 0.2.0",
|
|
||||||
"syn 2.0.65",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "parse-display-derive"
|
name = "parse-display-derive"
|
||||||
version = "0.9.0"
|
version = "0.9.0"
|
||||||
@ -3407,8 +3372,8 @@ dependencies = [
|
|||||||
"quote",
|
"quote",
|
||||||
"regex",
|
"regex",
|
||||||
"regex-syntax 0.8.3",
|
"regex-syntax 0.8.3",
|
||||||
"structmeta 0.3.0",
|
"structmeta",
|
||||||
"syn 2.0.65",
|
"syn 2.0.66",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -3550,7 +3515,7 @@ dependencies = [
|
|||||||
"phf_shared 0.11.2",
|
"phf_shared 0.11.2",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.65",
|
"syn 2.0.66",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -3582,14 +3547,14 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "phonenumber"
|
name = "phonenumber"
|
||||||
version = "0.3.4+8.13.34"
|
version = "0.3.5+8.13.36"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8d888d375f2963bf06c5079665fbe53db69860879ff5a78524fe3c93c54fb7b8"
|
checksum = "f174c8db59b620032bd52b655fc97000458850fec0db35fcd4e802b668517ec0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bincode",
|
"bincode",
|
||||||
"either",
|
"either",
|
||||||
"fnv",
|
"fnv",
|
||||||
"itertools 0.12.1",
|
"itertools",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"nom",
|
"nom",
|
||||||
"quick-xml",
|
"quick-xml",
|
||||||
@ -3618,7 +3583,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.65",
|
"syn 2.0.66",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -3770,9 +3735,9 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.81"
|
version = "1.0.83"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba"
|
checksum = "0b33eb56c327dec362a9e55b3ad14f9d2f0904fb5a5b03b513ab5465399e9f43"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
@ -4002,12 +3967,6 @@ version = "0.6.29"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
|
checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "regex-syntax"
|
|
||||||
version = "0.7.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex-syntax"
|
name = "regex-syntax"
|
||||||
version = "0.8.3"
|
version = "0.8.3"
|
||||||
@ -4456,7 +4415,7 @@ dependencies = [
|
|||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"serde_derive_internals",
|
"serde_derive_internals",
|
||||||
"syn 2.0.65",
|
"syn 2.0.66",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -4565,7 +4524,7 @@ checksum = "6048858004bcff69094cd972ed40a32500f153bd3be9f716b2eed2e8217c4838"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.65",
|
"syn 2.0.66",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -4576,7 +4535,7 @@ checksum = "330f01ce65a3a5fe59a60c82f3c9a024b573b8a6e875bd233fe5f934e71d54e3"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.65",
|
"syn 2.0.66",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -4609,7 +4568,7 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.65",
|
"syn 2.0.66",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -4630,7 +4589,7 @@ dependencies = [
|
|||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"serde",
|
"serde",
|
||||||
"syn 2.0.65",
|
"syn 2.0.66",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -4672,7 +4631,7 @@ dependencies = [
|
|||||||
"darling",
|
"darling",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.65",
|
"syn 2.0.66",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -4931,18 +4890,6 @@ version = "0.11.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "structmeta"
|
|
||||||
version = "0.2.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "78ad9e09554f0456d67a69c1584c9798ba733a5b50349a6c0d0948710523922d"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"structmeta-derive 0.2.0",
|
|
||||||
"syn 2.0.65",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "structmeta"
|
name = "structmeta"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
@ -4951,19 +4898,8 @@ checksum = "2e1575d8d40908d70f6fd05537266b90ae71b15dbbe7a8b7dffa2b759306d329"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"structmeta-derive 0.3.0",
|
"structmeta-derive",
|
||||||
"syn 2.0.65",
|
"syn 2.0.66",
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "structmeta-derive"
|
|
||||||
version = "0.2.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a60bcaff7397072dca0017d1db428e30d5002e00b6847703e2e42005c95fbe00"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn 2.0.65",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -4974,7 +4910,7 @@ checksum = "152a0b65a590ff6c3da95cabe2353ee04e6167c896b28e3b14478c2636c922fc"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.65",
|
"syn 2.0.66",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -4996,7 +4932,7 @@ dependencies = [
|
|||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"rustversion",
|
"rustversion",
|
||||||
"syn 2.0.65",
|
"syn 2.0.66",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -5029,9 +4965,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.65"
|
version = "2.0.66"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d2863d96a84c6439701d7a38f9de935ec562c8832cc55d1dde0f513b52fad106"
|
checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@ -5047,7 +4983,7 @@ dependencies = [
|
|||||||
"proc-macro-error",
|
"proc-macro-error",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.65",
|
"syn 2.0.66",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -5064,7 +5000,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.65",
|
"syn 2.0.66",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -5281,7 +5217,7 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"sha2",
|
"sha2",
|
||||||
"syn 2.0.65",
|
"syn 2.0.66",
|
||||||
"tauri-utils",
|
"tauri-utils",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"time",
|
"time",
|
||||||
@ -5299,7 +5235,7 @@ dependencies = [
|
|||||||
"heck 0.4.1",
|
"heck 0.4.1",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.65",
|
"syn 2.0.66",
|
||||||
"tauri-codegen",
|
"tauri-codegen",
|
||||||
"tauri-utils",
|
"tauri-utils",
|
||||||
]
|
]
|
||||||
@ -5665,7 +5601,7 @@ checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.65",
|
"syn 2.0.66",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -5754,7 +5690,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.65",
|
"syn 2.0.66",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -5943,7 +5879,7 @@ checksum = "84fd902d4e0b9a4b27f2f440108dc034e1758628a9b702f8ec61ad66355422fa"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.65",
|
"syn 2.0.66",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -5972,7 +5908,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.65",
|
"syn 2.0.66",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -6093,7 +6029,7 @@ source = "git+https://github.com/Aleph-Alpha/ts-rs#f898578d80d3e2a54080c1c046c45
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.65",
|
"syn 2.0.66",
|
||||||
"termcolor",
|
"termcolor",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -6306,7 +6242,7 @@ dependencies = [
|
|||||||
"proc-macro-error",
|
"proc-macro-error",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.65",
|
"syn 2.0.66",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -6405,7 +6341,7 @@ dependencies = [
|
|||||||
"once_cell",
|
"once_cell",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.65",
|
"syn 2.0.66",
|
||||||
"wasm-bindgen-shared",
|
"wasm-bindgen-shared",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -6439,7 +6375,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.65",
|
"syn 2.0.66",
|
||||||
"wasm-bindgen-backend",
|
"wasm-bindgen-backend",
|
||||||
"wasm-bindgen-shared",
|
"wasm-bindgen-shared",
|
||||||
]
|
]
|
||||||
@ -6580,7 +6516,7 @@ checksum = "ac1345798ecd8122468840bcdf1b95e5dc6d2206c5e4b0eafa078d061f59c9bc"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.65",
|
"syn 2.0.66",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -6686,7 +6622,7 @@ checksum = "f6fc35f58ecd95a9b71c4f2329b911016e6bec66b3f2e6a4aad86bd2e99e2f9b"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.65",
|
"syn 2.0.66",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -6697,7 +6633,7 @@ checksum = "08990546bf4edef8f431fa6326e032865f27138718c587dc21bc0265bbcb57cc"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.65",
|
"syn 2.0.66",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -7139,7 +7075,7 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.65",
|
"syn 2.0.66",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -11,6 +11,7 @@ import {
|
|||||||
InterpreterFrom,
|
InterpreterFrom,
|
||||||
Prop,
|
Prop,
|
||||||
StateFrom,
|
StateFrom,
|
||||||
|
assign,
|
||||||
} from 'xstate'
|
} from 'xstate'
|
||||||
import { useCommandsContext } from 'hooks/useCommandsContext'
|
import { useCommandsContext } from 'hooks/useCommandsContext'
|
||||||
import { fileMachine } from 'machines/fileMachine'
|
import { fileMachine } from 'machines/fileMachine'
|
||||||
@ -37,7 +38,7 @@ export const FileMachineProvider = ({
|
|||||||
}) => {
|
}) => {
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
const { commandBarSend } = useCommandsContext()
|
const { commandBarSend } = useCommandsContext()
|
||||||
const { project } = useRouteLoaderData(paths.FILE) as IndexLoaderData
|
const { project, file } = useRouteLoaderData(paths.FILE) as IndexLoaderData
|
||||||
|
|
||||||
const [state, send] = useMachine(fileMachine, {
|
const [state, send] = useMachine(fileMachine, {
|
||||||
context: {
|
context: {
|
||||||
@ -53,8 +54,32 @@ export const FileMachineProvider = ({
|
|||||||
context.selectedDirectory + sep() + event.data.name
|
context.selectedDirectory + sep() + event.data.name
|
||||||
)}`
|
)}`
|
||||||
)
|
)
|
||||||
|
} else if (
|
||||||
|
event.data &&
|
||||||
|
'path' in event.data &&
|
||||||
|
event.data.path.endsWith(FILE_EXT)
|
||||||
|
) {
|
||||||
|
// Don't navigate to newly created directories
|
||||||
|
navigate(`${paths.FILE}/${encodeURIComponent(event.data.path)}`)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
addFileToRenamingQueue: assign({
|
||||||
|
itemsBeingRenamed: (context, event) => [
|
||||||
|
...context.itemsBeingRenamed,
|
||||||
|
event.data.path,
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
removeFileFromRenamingQueue: assign({
|
||||||
|
itemsBeingRenamed: (
|
||||||
|
context,
|
||||||
|
event: EventFrom<typeof fileMachine, 'done.invoke.rename-file'>
|
||||||
|
) =>
|
||||||
|
context.itemsBeingRenamed.filter(
|
||||||
|
(path) => path !== event.data.oldPath
|
||||||
|
),
|
||||||
|
}),
|
||||||
|
renameToastSuccess: (_, event) => toast.success(event.data.message),
|
||||||
|
createToastSuccess: (_, event) => toast.success(event.data.message),
|
||||||
toastSuccess: (_, event) =>
|
toastSuccess: (_, event) =>
|
||||||
event.data && toast.success((event.data || '') + ''),
|
event.data && toast.success((event.data || '') + ''),
|
||||||
toastError: (_, event) => toast.error((event.data || '') + ''),
|
toastError: (_, event) => toast.error((event.data || '') + ''),
|
||||||
@ -70,37 +95,56 @@ export const FileMachineProvider = ({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
createFile: async (context, event) => {
|
createFile: async (context, event) => {
|
||||||
let name = event.data.name.trim() || DEFAULT_FILE_NAME
|
let createdName = event.data.name.trim() || DEFAULT_FILE_NAME
|
||||||
|
let createdPath: string
|
||||||
|
|
||||||
if (event.data.makeDir) {
|
if (event.data.makeDir) {
|
||||||
await mkdir(await join(context.selectedDirectory.path, name))
|
createdPath = await join(context.selectedDirectory.path, createdName)
|
||||||
|
await mkdir(createdPath)
|
||||||
} else {
|
} else {
|
||||||
await create(
|
createdPath =
|
||||||
context.selectedDirectory.path +
|
context.selectedDirectory.path +
|
||||||
sep() +
|
sep() +
|
||||||
name +
|
createdName +
|
||||||
(name.endsWith(FILE_EXT) ? '' : FILE_EXT)
|
(createdName.endsWith(FILE_EXT) ? '' : FILE_EXT)
|
||||||
)
|
await create(createdPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
return `Successfully created "${name}"`
|
return {
|
||||||
|
message: `Successfully created "${createdName}"`,
|
||||||
|
path: createdPath,
|
||||||
|
}
|
||||||
},
|
},
|
||||||
renameFile: async (
|
renameFile: async (
|
||||||
context: ContextFrom<typeof fileMachine>,
|
context: ContextFrom<typeof fileMachine>,
|
||||||
event: EventFrom<typeof fileMachine, 'Rename file'>
|
event: EventFrom<typeof fileMachine, 'Rename file'>
|
||||||
) => {
|
) => {
|
||||||
const { oldName, newName, isDir } = event.data
|
const { oldName, newName, isDir } = event.data
|
||||||
let name = newName ? newName : DEFAULT_FILE_NAME
|
const name = newName ? newName : DEFAULT_FILE_NAME
|
||||||
|
const oldPath = await join(context.selectedDirectory.path, oldName)
|
||||||
|
const newDirPath = await join(context.selectedDirectory.path, name)
|
||||||
|
const newPath =
|
||||||
|
newDirPath + (name.endsWith(FILE_EXT) || isDir ? '' : FILE_EXT)
|
||||||
|
|
||||||
await rename(
|
await rename(oldPath, newPath, {})
|
||||||
await join(context.selectedDirectory.path, oldName),
|
|
||||||
(await join(context.selectedDirectory.path, name)) +
|
if (oldPath === file?.path && project?.path) {
|
||||||
(name.endsWith(FILE_EXT) || isDir ? '' : FILE_EXT),
|
// If we just renamed the current file, navigate to the new path
|
||||||
{}
|
navigate(paths.FILE + '/' + encodeURIComponent(newPath))
|
||||||
)
|
} else if (file?.path.includes(oldPath)) {
|
||||||
return (
|
// If we just renamed a directory that the current file is in, navigate to the new path
|
||||||
oldName !== name && `Successfully renamed "${oldName}" to "${name}"`
|
navigate(
|
||||||
)
|
paths.FILE +
|
||||||
|
'/' +
|
||||||
|
encodeURIComponent(file.path.replace(oldPath, newDirPath))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
message: `Successfully renamed "${oldName}" to "${name}"`,
|
||||||
|
newPath,
|
||||||
|
oldPath,
|
||||||
|
}
|
||||||
},
|
},
|
||||||
deleteFile: async (
|
deleteFile: async (
|
||||||
context: ContextFrom<typeof fileMachine>,
|
context: ContextFrom<typeof fileMachine>,
|
||||||
@ -117,6 +161,17 @@ export const FileMachineProvider = ({
|
|||||||
console.error('Error deleting file', e)
|
console.error('Error deleting file', e)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we just deleted the current file or one of its parent directories,
|
||||||
|
// navigate to the project root
|
||||||
|
if (
|
||||||
|
(event.data.path === file?.path ||
|
||||||
|
file?.path.includes(event.data.path)) &&
|
||||||
|
project?.path
|
||||||
|
) {
|
||||||
|
navigate(paths.FILE + '/' + encodeURIComponent(project.path))
|
||||||
|
}
|
||||||
|
|
||||||
return `Successfully deleted ${isDir ? 'folder' : 'file'} "${
|
return `Successfully deleted ${isDir ? 'folder' : 'file'} "${
|
||||||
event.data.name
|
event.data.name
|
||||||
}"`
|
}"`
|
||||||
|
@ -2,11 +2,11 @@ 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 { Dispatch, useEffect, useRef, useState } from 'react'
|
import { Dispatch, useCallback, useEffect, useRef, useState } from 'react'
|
||||||
import { useNavigate, useRouteLoaderData } from 'react-router-dom'
|
import { useNavigate, useRouteLoaderData } from 'react-router-dom'
|
||||||
import { Dialog, Disclosure } from '@headlessui/react'
|
import { Disclosure } from '@headlessui/react'
|
||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||||
import { faChevronRight, faTrashAlt } from '@fortawesome/free-solid-svg-icons'
|
import { faChevronRight } from '@fortawesome/free-solid-svg-icons'
|
||||||
import { useFileContext } from 'hooks/useFileContext'
|
import { useFileContext } from 'hooks/useFileContext'
|
||||||
import styles from './FileTree.module.css'
|
import styles from './FileTree.module.css'
|
||||||
import { sortProject } from 'lib/tauriFS'
|
import { sortProject } from 'lib/tauriFS'
|
||||||
@ -16,6 +16,8 @@ import { codeManager, kclManager } from 'lib/singletons'
|
|||||||
import { useDocumentHasFocus } from 'hooks/useDocumentHasFocus'
|
import { useDocumentHasFocus } from 'hooks/useDocumentHasFocus'
|
||||||
import { useLspContext } from './LspProvider'
|
import { useLspContext } from './LspProvider'
|
||||||
import useHotkeyWrapper from 'lib/hotkeyWrapper'
|
import useHotkeyWrapper from 'lib/hotkeyWrapper'
|
||||||
|
import { useModelingContext } from 'hooks/useModelingContext'
|
||||||
|
import { DeleteConfirmationDialog } from './ProjectCard/DeleteProjectDialog'
|
||||||
|
|
||||||
function getIndentationCSS(level: number) {
|
function getIndentationCSS(level: number) {
|
||||||
return `calc(1rem * ${level + 1})`
|
return `calc(1rem * ${level + 1})`
|
||||||
@ -23,11 +25,11 @@ function getIndentationCSS(level: number) {
|
|||||||
|
|
||||||
function RenameForm({
|
function RenameForm({
|
||||||
fileOrDir,
|
fileOrDir,
|
||||||
setIsRenaming,
|
onSubmit,
|
||||||
level = 0,
|
level = 0,
|
||||||
}: {
|
}: {
|
||||||
fileOrDir: FileEntry
|
fileOrDir: FileEntry
|
||||||
setIsRenaming: Dispatch<React.SetStateAction<boolean>>
|
onSubmit: () => void
|
||||||
level?: number
|
level?: number
|
||||||
}) {
|
}) {
|
||||||
const { send } = useFileContext()
|
const { send } = useFileContext()
|
||||||
@ -35,7 +37,6 @@ function RenameForm({
|
|||||||
|
|
||||||
function handleRenameSubmit(e: React.FormEvent<HTMLFormElement>) {
|
function handleRenameSubmit(e: React.FormEvent<HTMLFormElement>) {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
setIsRenaming(false)
|
|
||||||
send({
|
send({
|
||||||
type: 'Rename file',
|
type: 'Rename file',
|
||||||
data: {
|
data: {
|
||||||
@ -49,7 +50,7 @@ function RenameForm({
|
|||||||
function handleKeyDown(e: React.KeyboardEvent<HTMLInputElement>) {
|
function handleKeyDown(e: React.KeyboardEvent<HTMLInputElement>) {
|
||||||
if (e.key === 'Escape') {
|
if (e.key === 'Escape') {
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
setIsRenaming(false)
|
onSubmit()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,10 +62,12 @@ function RenameForm({
|
|||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
type="text"
|
type="text"
|
||||||
autoFocus
|
autoFocus
|
||||||
|
autoCapitalize="off"
|
||||||
|
autoCorrect="off"
|
||||||
placeholder={fileOrDir.name}
|
placeholder={fileOrDir.name}
|
||||||
className="w-full py-1 bg-transparent text-chalkboard-100 placeholder:text-chalkboard-70 dark:text-chalkboard-10 dark:placeholder:text-chalkboard-50 focus:outline-none focus:ring-0"
|
className="w-full py-1 bg-transparent text-chalkboard-100 placeholder:text-chalkboard-70 dark:text-chalkboard-10 dark:placeholder:text-chalkboard-50 focus:outline-none focus:ring-0"
|
||||||
onKeyDown={handleKeyDown}
|
onKeyDown={handleKeyDown}
|
||||||
onBlur={() => setIsRenaming(false)}
|
onBlur={onSubmit}
|
||||||
style={{ paddingInlineStart: getIndentationCSS(level) }}
|
style={{ paddingInlineStart: getIndentationCSS(level) }}
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
@ -75,7 +78,7 @@ function RenameForm({
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function DeleteConfirmationDialog({
|
function DeleteFileTreeItemDialog({
|
||||||
fileOrDir,
|
fileOrDir,
|
||||||
setIsOpen,
|
setIsOpen,
|
||||||
}: {
|
}: {
|
||||||
@ -84,48 +87,23 @@ function DeleteConfirmationDialog({
|
|||||||
}) {
|
}) {
|
||||||
const { send } = useFileContext()
|
const { send } = useFileContext()
|
||||||
return (
|
return (
|
||||||
<Dialog
|
<DeleteConfirmationDialog
|
||||||
open={true}
|
title={`Delete ${fileOrDir.children !== undefined ? 'folder' : 'file'}`}
|
||||||
onClose={() => setIsOpen(false)}
|
onDismiss={() => setIsOpen(false)}
|
||||||
className="relative z-50"
|
onConfirm={() => {
|
||||||
|
send({ type: 'Delete file', data: fileOrDir })
|
||||||
|
setIsOpen(false)
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<div className="fixed inset-0 bg-chalkboard-110/80 grid place-content-center">
|
<p className="my-4">
|
||||||
<Dialog.Panel className="rounded p-4 bg-chalkboard-10 dark:bg-chalkboard-100 border border-destroy-80 max-w-2xl">
|
This will permanently delete "{fileOrDir.name || 'this file'}"
|
||||||
<Dialog.Title as="h2" className="text-2xl font-bold mb-4">
|
{fileOrDir.children !== undefined ? ' and all of its contents. ' : '. '}
|
||||||
Delete {fileOrDir.children !== undefined ? 'Folder' : 'File'}
|
</p>
|
||||||
</Dialog.Title>
|
<p className="my-4">
|
||||||
<Dialog.Description className="my-6">
|
Are you sure you want to delete "{fileOrDir.name || 'this file'}
|
||||||
This will permanently delete "{fileOrDir.name || 'this file'}"
|
"? This action cannot be undone.
|
||||||
{fileOrDir.children !== undefined
|
</p>
|
||||||
? ' and all of its contents. '
|
</DeleteConfirmationDialog>
|
||||||
: '. '}
|
|
||||||
This action cannot be undone.
|
|
||||||
</Dialog.Description>
|
|
||||||
|
|
||||||
<div className="flex justify-between">
|
|
||||||
<ActionButton
|
|
||||||
Element="button"
|
|
||||||
onClick={async () => {
|
|
||||||
send({ type: 'Delete file', data: fileOrDir })
|
|
||||||
setIsOpen(false)
|
|
||||||
}}
|
|
||||||
iconStart={{
|
|
||||||
icon: faTrashAlt,
|
|
||||||
bgClassName: 'bg-destroy-80',
|
|
||||||
iconClassName:
|
|
||||||
'text-destroy-20 group-hover:text-destroy-10 hover:text-destroy-10 dark:text-destroy-20 dark:group-hover:text-destroy-10 dark:hover:text-destroy-10',
|
|
||||||
}}
|
|
||||||
className="hover:border-destroy-40 dark:hover:border-destroy-40"
|
|
||||||
>
|
|
||||||
Delete
|
|
||||||
</ActionButton>
|
|
||||||
<ActionButton Element="button" onClick={() => setIsOpen(false)}>
|
|
||||||
Cancel
|
|
||||||
</ActionButton>
|
|
||||||
</div>
|
|
||||||
</Dialog.Panel>
|
|
||||||
</div>
|
|
||||||
</Dialog>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,35 +111,57 @@ const FileTreeItem = ({
|
|||||||
project,
|
project,
|
||||||
currentFile,
|
currentFile,
|
||||||
fileOrDir,
|
fileOrDir,
|
||||||
onDoubleClick,
|
onNavigateToFile,
|
||||||
level = 0,
|
level = 0,
|
||||||
}: {
|
}: {
|
||||||
project?: IndexLoaderData['project']
|
project?: IndexLoaderData['project']
|
||||||
currentFile?: IndexLoaderData['file']
|
currentFile?: IndexLoaderData['file']
|
||||||
fileOrDir: FileEntry
|
fileOrDir: FileEntry
|
||||||
onDoubleClick?: () => void
|
onNavigateToFile?: () => void
|
||||||
level?: number
|
level?: number
|
||||||
}) => {
|
}) => {
|
||||||
const { send, context } = useFileContext()
|
const { send: fileSend, context: fileContext } = useFileContext()
|
||||||
const { onFileOpen, onFileClose } = useLspContext()
|
const { onFileOpen, onFileClose } = useLspContext()
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
const [isRenaming, setIsRenaming] = useState(false)
|
|
||||||
const [isConfirmingDelete, setIsConfirmingDelete] = useState(false)
|
const [isConfirmingDelete, setIsConfirmingDelete] = useState(false)
|
||||||
const isCurrentFile = fileOrDir.path === currentFile?.path
|
const isCurrentFile = fileOrDir.path === currentFile?.path
|
||||||
|
|
||||||
|
const isRenaming = fileContext.itemsBeingRenamed.includes(fileOrDir.path)
|
||||||
|
const removeCurrentItemFromRenaming = useCallback(
|
||||||
|
() =>
|
||||||
|
fileSend({
|
||||||
|
type: 'assign',
|
||||||
|
data: {
|
||||||
|
itemsBeingRenamed: fileContext.itemsBeingRenamed.filter(
|
||||||
|
(path) => path !== fileOrDir.path
|
||||||
|
),
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
[fileContext.itemsBeingRenamed, fileOrDir.path, fileSend]
|
||||||
|
)
|
||||||
|
|
||||||
|
const addCurrentItemToRenaming = useCallback(() => {
|
||||||
|
fileSend({
|
||||||
|
type: 'assign',
|
||||||
|
data: {
|
||||||
|
itemsBeingRenamed: [...fileContext.itemsBeingRenamed, fileOrDir.path],
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}, [fileContext.itemsBeingRenamed, fileOrDir.path, fileSend])
|
||||||
|
|
||||||
function handleKeyUp(e: React.KeyboardEvent<HTMLButtonElement>) {
|
function handleKeyUp(e: React.KeyboardEvent<HTMLButtonElement>) {
|
||||||
if (e.metaKey && e.key === 'Backspace') {
|
if (e.metaKey && e.key === 'Backspace') {
|
||||||
// Open confirmation dialog
|
// Open confirmation dialog
|
||||||
setIsConfirmingDelete(true)
|
setIsConfirmingDelete(true)
|
||||||
} else if (e.key === 'Enter') {
|
} else if (e.key === 'Enter') {
|
||||||
// Show the renaming form
|
// Show the renaming form
|
||||||
setIsRenaming(true)
|
addCurrentItemToRenaming()
|
||||||
} else if (e.code === 'Space') {
|
} else if (e.code === 'Space') {
|
||||||
handleDoubleClick()
|
handleClick()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleDoubleClick() {
|
function handleClick() {
|
||||||
if (fileOrDir.children !== undefined) return // Don't open directories
|
if (fileOrDir.children !== undefined) return // Don't open directories
|
||||||
|
|
||||||
if (fileOrDir.name?.endsWith(FILE_EXT) === false && project?.path) {
|
if (fileOrDir.name?.endsWith(FILE_EXT) === false && project?.path) {
|
||||||
@ -181,7 +181,7 @@ const FileTreeItem = ({
|
|||||||
// Open kcl files
|
// Open kcl files
|
||||||
navigate(`${paths.FILE}/${encodeURIComponent(fileOrDir.path)}`)
|
navigate(`${paths.FILE}/${encodeURIComponent(fileOrDir.path)}`)
|
||||||
}
|
}
|
||||||
onDoubleClick?.()
|
onNavigateToFile?.()
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -199,8 +199,10 @@ const FileTreeItem = ({
|
|||||||
<button
|
<button
|
||||||
className="flex gap-1 items-center py-0.5 rounded-none border-none p-0 m-0 text-sm w-full hover:!bg-transparent text-left !text-inherit"
|
className="flex gap-1 items-center py-0.5 rounded-none border-none p-0 m-0 text-sm w-full hover:!bg-transparent text-left !text-inherit"
|
||||||
style={{ paddingInlineStart: getIndentationCSS(level) }}
|
style={{ paddingInlineStart: getIndentationCSS(level) }}
|
||||||
onDoubleClick={handleDoubleClick}
|
onClick={(e) => {
|
||||||
onClick={(e) => e.currentTarget.focus()}
|
e.currentTarget.focus()
|
||||||
|
handleClick()
|
||||||
|
}}
|
||||||
onKeyUp={handleKeyUp}
|
onKeyUp={handleKeyUp}
|
||||||
>
|
>
|
||||||
<CustomIcon
|
<CustomIcon
|
||||||
@ -212,7 +214,7 @@ const FileTreeItem = ({
|
|||||||
) : (
|
) : (
|
||||||
<RenameForm
|
<RenameForm
|
||||||
fileOrDir={fileOrDir}
|
fileOrDir={fileOrDir}
|
||||||
setIsRenaming={setIsRenaming}
|
onSubmit={removeCurrentItemFromRenaming}
|
||||||
level={level}
|
level={level}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
@ -225,17 +227,23 @@ const FileTreeItem = ({
|
|||||||
<Disclosure.Button
|
<Disclosure.Button
|
||||||
className={
|
className={
|
||||||
' group border-none text-sm rounded-none p-0 m-0 flex items-center justify-start w-full py-0.5 hover:text-primary hover:bg-primary/5 dark:hover:text-inherit dark:hover:bg-primary/10' +
|
' group border-none text-sm rounded-none p-0 m-0 flex items-center justify-start w-full py-0.5 hover:text-primary hover:bg-primary/5 dark:hover:text-inherit dark:hover:bg-primary/10' +
|
||||||
(context.selectedDirectory.path.includes(fileOrDir.path)
|
(fileContext.selectedDirectory.path.includes(fileOrDir.path)
|
||||||
? ' ui-open:bg-primary/10'
|
? ' ui-open:bg-primary/10'
|
||||||
: '')
|
: '')
|
||||||
}
|
}
|
||||||
style={{ paddingInlineStart: getIndentationCSS(level) }}
|
style={{ paddingInlineStart: getIndentationCSS(level) }}
|
||||||
onClick={(e) => e.currentTarget.focus()}
|
onClick={(e) => e.currentTarget.focus()}
|
||||||
onClickCapture={(e) =>
|
onClickCapture={(e) =>
|
||||||
send({ type: 'Set selected directory', data: fileOrDir })
|
fileSend({
|
||||||
|
type: 'Set selected directory',
|
||||||
|
data: fileOrDir,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
onFocusCapture={(e) =>
|
onFocusCapture={(e) =>
|
||||||
send({ type: 'Set selected directory', data: fileOrDir })
|
fileSend({
|
||||||
|
type: 'Set selected directory',
|
||||||
|
data: fileOrDir,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
onKeyDown={(e) => e.key === 'Enter' && e.preventDefault()}
|
onKeyDown={(e) => e.key === 'Enter' && e.preventDefault()}
|
||||||
onKeyUp={handleKeyUp}
|
onKeyUp={handleKeyUp}
|
||||||
@ -263,7 +271,7 @@ const FileTreeItem = ({
|
|||||||
/>
|
/>
|
||||||
<RenameForm
|
<RenameForm
|
||||||
fileOrDir={fileOrDir}
|
fileOrDir={fileOrDir}
|
||||||
setIsRenaming={setIsRenaming}
|
onSubmit={removeCurrentItemFromRenaming}
|
||||||
level={-1}
|
level={-1}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@ -279,10 +287,16 @@ const FileTreeItem = ({
|
|||||||
<ul
|
<ul
|
||||||
className="m-0 p-0"
|
className="m-0 p-0"
|
||||||
onClickCapture={(e) => {
|
onClickCapture={(e) => {
|
||||||
send({ type: 'Set selected directory', data: fileOrDir })
|
fileSend({
|
||||||
|
type: 'Set selected directory',
|
||||||
|
data: fileOrDir,
|
||||||
|
})
|
||||||
}}
|
}}
|
||||||
onFocusCapture={(e) =>
|
onFocusCapture={(e) =>
|
||||||
send({ type: 'Set selected directory', data: fileOrDir })
|
fileSend({
|
||||||
|
type: 'Set selected directory',
|
||||||
|
data: fileOrDir,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{fileOrDir.children?.map((child) => (
|
{fileOrDir.children?.map((child) => (
|
||||||
@ -290,7 +304,7 @@ const FileTreeItem = ({
|
|||||||
fileOrDir={child}
|
fileOrDir={child}
|
||||||
project={project}
|
project={project}
|
||||||
currentFile={currentFile}
|
currentFile={currentFile}
|
||||||
onDoubleClick={onDoubleClick}
|
onNavigateToFile={onNavigateToFile}
|
||||||
level={level + 1}
|
level={level + 1}
|
||||||
key={level + '-' + child.path}
|
key={level + '-' + child.path}
|
||||||
/>
|
/>
|
||||||
@ -302,7 +316,7 @@ const FileTreeItem = ({
|
|||||||
</Disclosure>
|
</Disclosure>
|
||||||
)}
|
)}
|
||||||
{isConfirmingDelete && (
|
{isConfirmingDelete && (
|
||||||
<DeleteConfirmationDialog
|
<DeleteFileTreeItemDialog
|
||||||
fileOrDir={fileOrDir}
|
fileOrDir={fileOrDir}
|
||||||
setIsOpen={setIsConfirmingDelete}
|
setIsOpen={setIsConfirmingDelete}
|
||||||
/>
|
/>
|
||||||
@ -314,7 +328,7 @@ const FileTreeItem = ({
|
|||||||
interface FileTreeProps {
|
interface FileTreeProps {
|
||||||
className?: string
|
className?: string
|
||||||
file?: IndexLoaderData['file']
|
file?: IndexLoaderData['file']
|
||||||
closePanel: (
|
onNavigateToFile: (
|
||||||
focusableElement?:
|
focusableElement?:
|
||||||
| HTMLElement
|
| HTMLElement
|
||||||
| React.MutableRefObject<HTMLElement | null>
|
| React.MutableRefObject<HTMLElement | null>
|
||||||
@ -371,30 +385,34 @@ export const FileTreeMenu = () => {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const FileTree = ({ className = '', closePanel }: FileTreeProps) => {
|
export const FileTree = ({
|
||||||
|
className = '',
|
||||||
|
onNavigateToFile: closePanel,
|
||||||
|
}: FileTreeProps) => {
|
||||||
return (
|
return (
|
||||||
<div className={className}>
|
<div className={className}>
|
||||||
<div className="flex items-center gap-1 px-4 py-1 bg-chalkboard-20/40 dark:bg-chalkboard-80/50 border-b border-b-chalkboard-30 dark:border-b-chalkboard-80">
|
<div className="flex items-center gap-1 px-4 py-1 bg-chalkboard-20/40 dark:bg-chalkboard-80/50 border-b border-b-chalkboard-30 dark:border-b-chalkboard-80">
|
||||||
<h2 className="flex-1 m-0 p-0 text-sm mono">Files</h2>
|
<h2 className="flex-1 m-0 p-0 text-sm mono">Files</h2>
|
||||||
<FileTreeMenu />
|
<FileTreeMenu />
|
||||||
</div>
|
</div>
|
||||||
<FileTreeInner onDoubleClick={closePanel} />
|
<FileTreeInner onNavigateToFile={closePanel} />
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const FileTreeInner = ({
|
export const FileTreeInner = ({
|
||||||
onDoubleClick,
|
onNavigateToFile,
|
||||||
}: {
|
}: {
|
||||||
onDoubleClick?: () => void
|
onNavigateToFile?: () => void
|
||||||
}) => {
|
}) => {
|
||||||
const loaderData = useRouteLoaderData(paths.FILE) as IndexLoaderData
|
const loaderData = useRouteLoaderData(paths.FILE) as IndexLoaderData
|
||||||
const { send, context } = useFileContext()
|
const { send: fileSend, context: fileContext } = useFileContext()
|
||||||
|
const { send: modelingSend } = useModelingContext()
|
||||||
const documentHasFocus = useDocumentHasFocus()
|
const documentHasFocus = useDocumentHasFocus()
|
||||||
|
|
||||||
// Refresh the file tree when the document gets focus
|
// Refresh the file tree when the document gets focus
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
send({ type: 'Refresh' })
|
fileSend({ type: 'Refresh' })
|
||||||
}, [documentHasFocus])
|
}, [documentHasFocus])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -402,15 +420,22 @@ export const FileTreeInner = ({
|
|||||||
<ul
|
<ul
|
||||||
className="m-0 p-0 text-sm"
|
className="m-0 p-0 text-sm"
|
||||||
onClickCapture={(e) => {
|
onClickCapture={(e) => {
|
||||||
send({ type: 'Set selected directory', data: context.project })
|
fileSend({
|
||||||
|
type: 'Set selected directory',
|
||||||
|
data: fileContext.project,
|
||||||
|
})
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{sortProject(context.project.children || []).map((fileOrDir) => (
|
{sortProject(fileContext.project?.children || []).map((fileOrDir) => (
|
||||||
<FileTreeItem
|
<FileTreeItem
|
||||||
project={context.project}
|
project={fileContext.project}
|
||||||
currentFile={loaderData?.file}
|
currentFile={loaderData?.file}
|
||||||
fileOrDir={fileOrDir}
|
fileOrDir={fileOrDir}
|
||||||
onDoubleClick={onDoubleClick}
|
onNavigateToFile={() => {
|
||||||
|
// Reset modeling state when navigating to a new file
|
||||||
|
modelingSend({ type: 'Cancel' })
|
||||||
|
onNavigateToFile?.()
|
||||||
|
}}
|
||||||
key={fileOrDir.path}
|
key={fileOrDir.path}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
|
@ -1,33 +1,26 @@
|
|||||||
import { Dialog } from '@headlessui/react'
|
import { Dialog } from '@headlessui/react'
|
||||||
import { ActionButton } from 'components/ActionButton'
|
import { ActionButton } from 'components/ActionButton'
|
||||||
|
|
||||||
interface DeleteProjectDialogProps {
|
interface DeleteConfirmationDialogProps extends React.PropsWithChildren<{}> {
|
||||||
projectName: string
|
title: string
|
||||||
onConfirm: () => void
|
onConfirm: () => void
|
||||||
onDismiss: () => void
|
onDismiss: () => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export function DeleteProjectDialog({
|
export function DeleteConfirmationDialog({
|
||||||
projectName,
|
title,
|
||||||
onConfirm,
|
onConfirm,
|
||||||
onDismiss,
|
onDismiss,
|
||||||
}: DeleteProjectDialogProps) {
|
children,
|
||||||
|
}: DeleteConfirmationDialogProps) {
|
||||||
return (
|
return (
|
||||||
<Dialog open={true} onClose={onDismiss} className="relative z-50">
|
<Dialog open={true} onClose={onDismiss} className="relative z-50">
|
||||||
<div className="fixed inset-0 grid bg-chalkboard-110/80 place-content-center">
|
<div className="fixed inset-0 grid bg-chalkboard-110/80 place-content-center">
|
||||||
<Dialog.Panel className="max-w-2xl p-4 border rounded bg-chalkboard-10 dark:bg-chalkboard-100 border-destroy-80">
|
<Dialog.Panel className="max-w-2xl p-4 border rounded bg-chalkboard-10 dark:bg-chalkboard-100 border-destroy-80">
|
||||||
<Dialog.Title as="h2" className="mb-4 text-2xl font-bold">
|
<Dialog.Title as="h2" className="mb-4 text-2xl font-bold">
|
||||||
Delete File
|
{title}
|
||||||
</Dialog.Title>
|
</Dialog.Title>
|
||||||
<Dialog.Description>
|
<Dialog.Description>{children}</Dialog.Description>
|
||||||
This will permanently delete "{projectName || 'this file'}
|
|
||||||
".
|
|
||||||
</Dialog.Description>
|
|
||||||
|
|
||||||
<p className="my-4">
|
|
||||||
Are you sure you want to delete "{projectName || 'this file'}
|
|
||||||
"? This action cannot be undone.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<div className="flex justify-between">
|
<div className="flex justify-between">
|
||||||
<ActionButton
|
<ActionButton
|
||||||
|
@ -5,7 +5,7 @@ import { ActionButton } from '../ActionButton'
|
|||||||
import { FILE_EXT } from 'lib/constants'
|
import { FILE_EXT } from 'lib/constants'
|
||||||
import { useHotkeys } from 'react-hotkeys-hook'
|
import { useHotkeys } from 'react-hotkeys-hook'
|
||||||
import Tooltip from '../Tooltip'
|
import Tooltip from '../Tooltip'
|
||||||
import { DeleteProjectDialog } from './DeleteProjectDialog'
|
import { DeleteConfirmationDialog } from './DeleteProjectDialog'
|
||||||
import { ProjectCardRenameForm } from './ProjectCardRenameForm'
|
import { ProjectCardRenameForm } from './ProjectCardRenameForm'
|
||||||
import { Project } from 'wasm-lib/kcl/bindings/Project'
|
import { Project } from 'wasm-lib/kcl/bindings/Project'
|
||||||
|
|
||||||
@ -160,14 +160,23 @@ function ProjectCard({
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{isConfirmingDelete && (
|
{isConfirmingDelete && (
|
||||||
<DeleteProjectDialog
|
<DeleteConfirmationDialog
|
||||||
projectName={project.name}
|
title="Delete Project"
|
||||||
onConfirm={async () => {
|
onConfirm={async () => {
|
||||||
await handleDeleteProject(project)
|
await handleDeleteProject(project)
|
||||||
setIsConfirmingDelete(false)
|
setIsConfirmingDelete(false)
|
||||||
}}
|
}}
|
||||||
onDismiss={() => setIsConfirmingDelete(false)}
|
onDismiss={() => setIsConfirmingDelete(false)}
|
||||||
/>
|
>
|
||||||
|
<p className="my-4">
|
||||||
|
This will permanently delete "{project.name || 'this file'}
|
||||||
|
".
|
||||||
|
</p>
|
||||||
|
<p className="my-4">
|
||||||
|
Are you sure you want to delete "{project.name || 'this file'}
|
||||||
|
"? This action cannot be undone.
|
||||||
|
</p>
|
||||||
|
</DeleteConfirmationDialog>
|
||||||
)}
|
)}
|
||||||
</li>
|
</li>
|
||||||
)
|
)
|
||||||
|
@ -158,7 +158,7 @@ function ProjectMenuPopover({
|
|||||||
<FileTree
|
<FileTree
|
||||||
file={file}
|
file={file}
|
||||||
className="overflow-hidden border-0 border-y border-chalkboard-30 dark:border-chalkboard-80"
|
className="overflow-hidden border-0 border-y border-chalkboard-30 dark:border-chalkboard-80"
|
||||||
closePanel={close}
|
onNavigateToFile={close}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<div className="flex-1 p-4 text-sm overflow-hidden">
|
<div className="flex-1 p-4 text-sm overflow-hidden">
|
||||||
|
@ -4,7 +4,7 @@ import { Project } from 'wasm-lib/kcl/bindings/Project'
|
|||||||
|
|
||||||
export const fileMachine = createMachine(
|
export const fileMachine = createMachine(
|
||||||
{
|
{
|
||||||
/** @xstate-layout N4IgpgJg5mDOIC5QDECWAbMACAtgQwGMALVAOzAGI9ZZUpSBtABgF1FQAHAe1oBdUupdiAAeiAKwBGcQDoALACYAHAE4AzGoUA2JXK1yANCACeiabOmSlGpkqsqAvg6NpMuQiXIyAEtSykuLAAzDDgKAGEAJzA8XmwQzGY2JBBuPgEhFLEESTVxWS1xBWVVcTU5PXEjUwRNFRkFWwB2FQVxJia5JnE5JxdQ92IyMB8-BLCAJTBSPBx40KThNNR+QWFslSVZJS1u3TUVSR1xJurEXSYZJslipismbTklPpBXbHwhr19YYNDYCOisXmiVYSx4Kwy6zMeQKRRKKjKFUKZwQPXqkjkmjUTCYWi0TQOCheb0GnhG31+mH+ABEwJg4pSwIsUstVplQNlcvkZIVikpSuVKijdFoZOItJJpEomtcYUTnK8Bh8yaMfuN-gB5DjTRnMzjgtlQnIwnlw-kIwXIkyIdSSGRKHF5XFqSwdYlKjzDVWM-4AZTAvCwsDpYAIcQgWAgqGiYa4kWMetSBshWTMNyaMkOuV0ChUBJUEpRnUuux6WmxGkkTF6CpJyq9URi-FIUEZFAgghGZAAblwANYjAiAuIAWnGidZKY50O5vPhiKF1oQcnF9q0myYCN2FSa4ndbnrXkbsTIrfGFDAkUicZkHHQsSCcZwMiHTbAY4WoJZybWqeNq82ddygUaQHiqJc7BkTRcwUOQjmKHR133d5PS8KYZhwU82w7Lwe37EZogw99xy-fV0l-adalzeQVForY1Ada4ni0FE5CaJRM0UAlmm6LRkNJL10NmLDz0va9Ilve9eEfSJn0I2ZiM-ZIyIhCjREQOoaLospGIxHYUQY0U8VaVoJUdB5+MPEZaXpETQnbTsZDwgcZAgENRxI5Sk3I9l1P-UVci6cUbg0JRlBRcRNkzHRdwUGVaPEOxLNQ6z3LszALyvG87wfJ9XPcxSQS8yc1M5PIMz0aU7gYuQCyOIsegaaUCTCwpnT42sPU+EYpjwKMWx9BzcNIXsXMBCAPypCcf187I7DUGQqweWDGgJNR8SLJ55AY9ibgLPJy2S7qZF6-qzz+IauxG-CZHGya4AYSRipmo15sWnFikUDoNA2pcXVkBQbFo7FuMkJojpVU70rCMTsqkmS5JiCb1WmnzXtyd7lq+tbfpqYoFEzSL9DqNofo6-oDxSigpiCaJYCIVHVNmxAtEaBpyxuZQ8iOaQUTBjNpWJxo2l3TpnheAI3PgFI6xSsE0b-EcWKXJWZBxHF2hAip0ySzrKeOikAh9eWmaNSVriappqy2CpWkkAzqLUJp8Q5h4DgRGsKZQg2xj+E3DT-c2OIlGVdwqFc4rUYUuntB0wesaQmhAvc9e9lVj2bc7MH9qc-OkNjMwFfkygLWqIpxe0cTsWCOiOE4IcE6ZhIG8Yc9KxBFFYlp5EkWirFB6Q1AbrwbIDaG2+ZnIegzTYLWLg59BUYUmAWwHKo3B51HlL2BLQpHoellSA8oooOOsSLGiRdowdY2r7RWu5OhdQLycVfWVS1aZx+-BXKPzmei70VLkvJcKhbBijKHicq3QQLiycEAA */
|
/** @xstate-layout N4IgpgJg5mDOIC5QDECWAbMACAtgQwGMALVAOzAGI9ZZUpSBtABgF1FQAHAe1oBdUupdiAAeiAKwBGcQDoALACYAHAE4AzGoUA2JXK1yANCACeiabOmSlGpkqsqAvg6NpMuQiXIUASmABmAE5wRMxsSCDcfAJC4WIIWgpMMtpqkgrKalJa0kamCJIA7AUySgX6mkwK4gXVckpOLhjY+MRkYDIAEtRYpFxYfk2wFADCQXi82AOYocKRqPyCwnGSmbJa4ulKquJqcnriuYiaKsm2BSpVTAVyTOJyDSCuzR5tnd1TcD5gpHg4k00zcJzBYxUBxFRKWRKLS3XRqFSSHTVQ4IXRJAppRJWSr6erOR5NdytchvWD9QYjMYTcnTVizHjzaJLMyrGTrTbbXb7FF3E6SOSaNRMJhaLQFeEKB5PImedpdMkfIYAETAmGpH0BnAZIOZ+VZ7OUnL26xRui0MnE2WkpQxq0l+OlLVlpJpnwA8hxvq7NRFtUzYizxGsNoaVDtjQcTIh1JISsLMiLUlIrlLCU7XvLXUMAMpgXhYWCqsAECYQLAQVBBEtcALGH3A-1gsxpYoIla6BQqcUqbIo65JGF3LRCjSSJj3B1pl4k0ZgcZkKCuigQQTtMgANy4AGt2gQqWAALQaulAv2LAP5ZQnaoQuR3K5KJg5KMIeFJJSJfQFeM7NSQ1NuOmM5UguS5gAEAQ1jIHDoOMfg1jgMh7nOExHgCJ5alE55NnqloyBCWjqIo0iVJGeR2DImidgociIukOiEQBzzEu0vg-DgoEfMuq4yBu27tEE7GHseYSYYy2GiEcTBqPIVQ1FcEL8toKIJOaaQXPY2TWOIeKNIB06sd8vycU0FDgZBATQbBvDwQEiGCb8wnoaJvpYaCkmvp28gqD5kJ-lc-LQiif7mqKFwXNk8aVExMqvCqaomZg3EknxO4yBARaoSJ9JubqKx4SsNyWmkGgfkoPIQvhOg1AoRQ+TpkgxUB7TxXmiWUOZUEwXBCHpZlTm0i5DYScsmTFHopRPn+cg9oifZ3MkNp-to4iJloTUGTIvh4BWpCLoqyVrqQm5pWMEBoZgsD1me7lxHYMljpUNGJOKahin2dTyH+BR2J2w6WmoG0sVtc67ftFIrilx38TIZ0XXADCSENN26vdMiPekihXBo70vkmyQ2D5Qrik+BRA8621g1mZkQV11m2fZoPw1dGGueJt2IGjGPPdjb0FCi6QKPh4g9gK1G-qKTj4r0GXwOEjoGTl7O6gomgWtcVR3kVH6GC+B5QuUlphtJKhaxOenMc6ma9FmSs6hekiFLGyjfnUdwzQokjBV5ahlGUqSVPCYbmwS+nA5mip242HmOz9bKFEU7t3rVaimjcJSPoU1jSAUnviOTryzvOe2ulHI1mHcraclsOyiyoPLCnGthpDcGLrGTk5hxTRkcSXHxlxzCDKEktSa-eOk0aajslLstyu9J1j2hbsUkq1-B900A95ZX+HV35demtJBMTRCwqdpoBckpT7Vy2J9s4RsSgzyLiQRqTKJ7CcOtYtcqSFetndLavA9N8dqW8HY7whGGP8+99D1xfCoWwFodiijGrcT2eInBAA */
|
||||||
id: 'File machine',
|
id: 'File machine',
|
||||||
|
|
||||||
initial: 'Reading files',
|
initial: 'Reading files',
|
||||||
@ -12,6 +12,7 @@ export const fileMachine = createMachine(
|
|||||||
context: {
|
context: {
|
||||||
project: {} as Project,
|
project: {} as Project,
|
||||||
selectedDirectory: {} as FileEntry,
|
selectedDirectory: {} as FileEntry,
|
||||||
|
itemsBeingRenamed: [] as string[],
|
||||||
},
|
},
|
||||||
|
|
||||||
on: {
|
on: {
|
||||||
@ -65,7 +66,11 @@ export const fileMachine = createMachine(
|
|||||||
onDone: [
|
onDone: [
|
||||||
{
|
{
|
||||||
target: 'Reading files',
|
target: 'Reading files',
|
||||||
actions: ['toastSuccess'],
|
actions: [
|
||||||
|
'createToastSuccess',
|
||||||
|
'addFileToRenamingQueue',
|
||||||
|
'navigateToFile',
|
||||||
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
onError: [
|
onError: [
|
||||||
@ -84,7 +89,7 @@ export const fileMachine = createMachine(
|
|||||||
onDone: [
|
onDone: [
|
||||||
{
|
{
|
||||||
target: '#File machine.Reading files',
|
target: '#File machine.Reading files',
|
||||||
actions: ['toastSuccess'],
|
actions: ['renameToastSuccess'],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
onError: [
|
onError: [
|
||||||
@ -94,6 +99,8 @@ export const fileMachine = createMachine(
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
||||||
|
exit: 'removeFileFromRenamingQueue',
|
||||||
},
|
},
|
||||||
|
|
||||||
'Deleting file': {
|
'Deleting file': {
|
||||||
@ -157,6 +164,21 @@ export const fileMachine = createMachine(
|
|||||||
type: 'done.invoke.read-files'
|
type: 'done.invoke.read-files'
|
||||||
data: Project
|
data: Project
|
||||||
}
|
}
|
||||||
|
| {
|
||||||
|
type: 'done.invoke.rename-file'
|
||||||
|
data: {
|
||||||
|
message: string
|
||||||
|
oldPath: string
|
||||||
|
newPath: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
type: 'done.invoke.create-file'
|
||||||
|
data: {
|
||||||
|
message: string
|
||||||
|
path: string
|
||||||
|
}
|
||||||
|
}
|
||||||
| { type: 'assign'; data: { [key: string]: any } }
|
| { type: 'assign'; data: { [key: string]: any } }
|
||||||
| { type: 'Refresh' },
|
| { type: 'Refresh' },
|
||||||
},
|
},
|
||||||
|
Reference in New Issue
Block a user