From 0f957fb1f22c21be5057817e4c4e55f0530c2a1b Mon Sep 17 00:00:00 2001 From: vcoppe Date: Mon, 26 Oct 2026 19:22:14 +0100 Subject: [PATCH] create route file action --- gpx-rs/src/api/commands.rs | 15 ++++- gpx-rs/src/engine/command/edit/metadata.rs | 3 + gpx-rs/src/engine/command/edit/new_route.rs | 1 + gpx-rs/src/engine/command/edit/new_track.rs | 2 + .../engine/command/edit/new_track_segment.rs | 1 + gpx-rs/src/engine/command/file/delete.rs | 2 + gpx-rs/src/engine/command/file/delete_all.rs | 2 + gpx-rs/src/engine/command/file/duplicate.rs | 1 + gpx-rs/src/engine/command/file/load.rs | 3 + gpx-rs/src/engine/command/file/new.rs | 59 +++++++++++++++++-- gpx-rs/src/engine/command/file/sync.rs | 1 + .../src/engine/command/tools/new_waypoint.rs | 6 ++ gpx-rs/src/engine/tests.rs | 2 + tauri/src/commands/files.rs | 8 ++- tauri/src/tests.rs | 2 +- tauri/src/workspace.rs | 12 ++-- wasm/src/command/files.rs | 15 +++-- wasm/src/tests.rs | 24 +++++--- website/src/lib/actions/file-actions.ts | 6 ++ website/src/lib/components/Menu.svelte | 7 ++- .../components/explorer/ExplorerRow.svelte | 12 +++- .../components/explorer/ExplorerTree.svelte | 15 +++-- .../lib/components/explorer/state.svelte.ts | 12 ++-- website/src/lib/engine/backend/tauri.ts | 5 +- website/src/lib/engine/backend/types.ts | 15 ++++- website/src/lib/engine/engine.test.ts | 9 +++ website/src/lib/engine/engine.ts | 21 ++++--- website/src/locales/be.json | 1 - website/src/locales/ca.json | 1 - website/src/locales/cs.json | 1 - website/src/locales/da.json | 1 - website/src/locales/de.json | 1 - website/src/locales/el.json | 1 - website/src/locales/en.json | 3 +- website/src/locales/es.json | 1 - website/src/locales/eu.json | 1 - website/src/locales/fi.json | 1 - website/src/locales/fr.json | 1 - website/src/locales/he.json | 1 - website/src/locales/hu.json | 1 - website/src/locales/id.json | 1 - website/src/locales/it.json | 1 - website/src/locales/ko.json | 1 - website/src/locales/lt.json | 1 - website/src/locales/lv.json | 1 - website/src/locales/nl.json | 1 - website/src/locales/no.json | 1 - website/src/locales/pl.json | 1 - website/src/locales/pt-BR.json | 1 - website/src/locales/pt.json | 1 - website/src/locales/ro.json | 1 - website/src/locales/ru.json | 1 - website/src/locales/sr.json | 1 - website/src/locales/sv.json | 1 - website/src/locales/th.json | 1 - website/src/locales/tr.json | 1 - website/src/locales/uk.json | 1 - website/src/locales/vi.json | 1 - website/src/locales/zh-HK.json | 1 - website/src/locales/zh.json | 1 - 60 files changed, 211 insertions(+), 85 deletions(-) diff --git a/gpx-rs/src/api/commands.rs b/gpx-rs/src/api/commands.rs index 70e7481ed..01d69c39c 100644 --- a/gpx-rs/src/api/commands.rs +++ b/gpx-rs/src/api/commands.rs @@ -148,21 +148,30 @@ pub fn redo(engine: &mut Engine) -> Outcome { // Files -/// Creates a file and selects it. With `lng` and `lat`, it starts with a track and a segment that -/// hold that trackpoint (at `ele`, 0 by default). +/// Creates a file and selects it. With `route`, it starts with a route. With `lng` and `lat`, it +/// starts with a segment that holds that trackpoint (at `ele`, 0 by default): the one of its route +/// with `route`, of a track otherwise. pub fn new_file( engine: &mut Engine, name: &str, lng: Option, lat: Option, ele: Option, + route: bool, ) -> Outcome { let trackpoint = lng.zip(lat).map(|(lng, lat)| engine::NewTrackpoint { lng, lat, ele: ele.unwrap_or_default(), }); - edit(engine, Command::New(engine::New { name, trackpoint })) + edit( + engine, + Command::New(engine::New { + name, + trackpoint, + route, + }), + ) } /// Loads files as a single command (one undo step). The files are in `data`, one after the other, diff --git a/gpx-rs/src/engine/command/edit/metadata.rs b/gpx-rs/src/engine/command/edit/metadata.rs index 2932bfdaa..e4f7053cb 100644 --- a/gpx-rs/src/engine/command/edit/metadata.rs +++ b/gpx-rs/src/engine/command/edit/metadata.rs @@ -59,12 +59,14 @@ mod tests { New { name: "first", trackpoint: None, + route: false, } .apply(&mut fx.state()) .unwrap(); New { name: "second", trackpoint: None, + route: false, } .apply(&mut fx.state()) .unwrap(); // now selected @@ -122,6 +124,7 @@ mod tests { New { name: "file", trackpoint: None, + route: false, } .apply(&mut fx.state()) .unwrap(); diff --git a/gpx-rs/src/engine/command/edit/new_route.rs b/gpx-rs/src/engine/command/edit/new_route.rs index 24d149cec..c4766adb2 100644 --- a/gpx-rs/src/engine/command/edit/new_route.rs +++ b/gpx-rs/src/engine/command/edit/new_route.rs @@ -36,6 +36,7 @@ mod tests { New { name: "file", trackpoint: None, + route: false, } .apply(&mut fx.state()) .unwrap(); diff --git a/gpx-rs/src/engine/command/edit/new_track.rs b/gpx-rs/src/engine/command/edit/new_track.rs index 5ac1fab26..70e52f29e 100644 --- a/gpx-rs/src/engine/command/edit/new_track.rs +++ b/gpx-rs/src/engine/command/edit/new_track.rs @@ -61,6 +61,7 @@ mod tests { New { name: "file", trackpoint: None, + route: false, } .apply(&mut fx.state()) .unwrap(); @@ -77,6 +78,7 @@ mod tests { New { name: "file", trackpoint: None, + route: false, } .apply(&mut fx.state()) .unwrap(); diff --git a/gpx-rs/src/engine/command/edit/new_track_segment.rs b/gpx-rs/src/engine/command/edit/new_track_segment.rs index fa8a15d8d..d58dc692c 100644 --- a/gpx-rs/src/engine/command/edit/new_track_segment.rs +++ b/gpx-rs/src/engine/command/edit/new_track_segment.rs @@ -29,6 +29,7 @@ mod tests { New { name: "file", trackpoint: None, + route: false, } .apply(&mut fx.state()) .unwrap(); diff --git a/gpx-rs/src/engine/command/file/delete.rs b/gpx-rs/src/engine/command/file/delete.rs index f7c5b7098..4fd751a40 100644 --- a/gpx-rs/src/engine/command/file/delete.rs +++ b/gpx-rs/src/engine/command/file/delete.rs @@ -146,6 +146,7 @@ mod tests { crate::New { name: "keep", trackpoint: None, + route: false, } .apply(&mut fx.state()) .unwrap(); @@ -280,6 +281,7 @@ mod tests { crate::New { name: "keep", trackpoint: None, + route: false, } .apply(&mut fx.state()) .unwrap(); diff --git a/gpx-rs/src/engine/command/file/delete_all.rs b/gpx-rs/src/engine/command/file/delete_all.rs index badc81d93..9f26b8e92 100644 --- a/gpx-rs/src/engine/command/file/delete_all.rs +++ b/gpx-rs/src/engine/command/file/delete_all.rs @@ -31,12 +31,14 @@ mod tests { crate::New { name: "a", trackpoint: None, + route: false, } .apply(&mut fx.state()) .unwrap(); crate::New { name: "b", trackpoint: None, + route: false, } .apply(&mut fx.state()) .unwrap(); diff --git a/gpx-rs/src/engine/command/file/duplicate.rs b/gpx-rs/src/engine/command/file/duplicate.rs index 9e5b5bef1..5ca0add48 100644 --- a/gpx-rs/src/engine/command/file/duplicate.rs +++ b/gpx-rs/src/engine/command/file/duplicate.rs @@ -217,6 +217,7 @@ mod tests { crate::New { name, trackpoint: None, + route: false, } .apply(&mut fx.state()) .unwrap(); diff --git a/gpx-rs/src/engine/command/file/load.rs b/gpx-rs/src/engine/command/file/load.rs index 734392be7..930b2d758 100644 --- a/gpx-rs/src/engine/command/file/load.rs +++ b/gpx-rs/src/engine/command/file/load.rs @@ -85,6 +85,7 @@ mod tests { crate::New { name: "keep", trackpoint: None, + route: false, } .apply(&mut fx.state()) .unwrap(); @@ -140,6 +141,7 @@ mod tests { crate::New { name: "before", trackpoint: None, + route: false, } .apply(&mut fx.state()) .unwrap(); @@ -189,6 +191,7 @@ mod tests { crate::New { name: "keep", trackpoint: None, + route: false, } .apply(&mut fx.state()) .unwrap(); diff --git a/gpx-rs/src/engine/command/file/new.rs b/gpx-rs/src/engine/command/file/new.rs index 7ecf31437..d548414e0 100644 --- a/gpx-rs/src/engine/command/file/new.rs +++ b/gpx-rs/src/engine/command/file/new.rs @@ -1,12 +1,16 @@ -use crate::{Apply, CommandError, File, LngLat, State, Track, TrackSegment, Trackpoint, produce}; +use crate::{ + Apply, CommandError, File, LngLat, Route, State, Track, TrackSegment, Trackpoint, produce, +}; -/// Creates an empty file and selects it. With a `trackpoint`, the file starts with a track and a -/// segment that hold it: it is how the routing tool starts a route on an empty map, in a single -/// undo step. +/// Creates an empty file and selects it. With `route`, the file starts with a route, which is +/// empty. With a `trackpoint`, the file starts with a segment that holds it, the one of its route +/// with `route` or of a track otherwise: it is how the routing tool starts a route on an empty map, +/// in a single undo step. #[derive(Debug)] pub struct New<'a> { pub name: &'a str, pub trackpoint: Option, + pub route: bool, } #[derive(Debug, Clone, Copy)] @@ -21,8 +25,8 @@ impl Apply for New<'_> { produce(state, |_| { let mut file = File::default(); file.info.name = self.name.to_owned(); + let mut segment = TrackSegment::default(); if let Some(point) = self.trackpoint { - let mut segment = TrackSegment::default(); // the ends of a segment are anchors of the routing tool segment.splice( 0, @@ -36,6 +40,13 @@ impl Apply for New<'_> { ..Default::default() }], ); + } + if self.route { + file.rte.push(Route { + seg: segment, + ..Default::default() + }); + } else if self.trackpoint.is_some() { file.trk.push(Track { trkseg: vec![segment], ..Default::default() @@ -59,7 +70,8 @@ mod tests { assert!( New { name: "new", - trackpoint: None + trackpoint: None, + route: false, } .apply(&mut fx.state()) .is_ok() @@ -83,6 +95,7 @@ mod tests { New { name: "new", trackpoint: Some(point), + route: false, } .apply(&mut fx.state()) .unwrap(); @@ -98,4 +111,38 @@ mod tests { assert_eq!(segment[0].anchor, Some(0)); assert_eq!(fx.selected_files(), [file.id].into()); } + + #[test] + fn test_new_with_a_route() { + let mut fx = Fixture::default(); + New { + name: "new", + trackpoint: None, + route: true, + } + .apply(&mut fx.state()) + .unwrap(); + let file = fx.files.values().next().unwrap(); + assert_eq!((file.rte.len(), file.trk.len()), (1, 0)); + assert!(file.rte[0].seg.is_empty()); + assert_eq!(fx.selected_files(), [file.id].into()); + + // the trackpoint goes to the route + let mut fx = Fixture::default(); + New { + name: "new", + trackpoint: Some(NewTrackpoint { + lng: 1.0, + lat: 2.0, + ele: 3.0, + }), + route: true, + } + .apply(&mut fx.state()) + .unwrap(); + let file = fx.files.values().next().unwrap(); + assert_eq!((file.rte.len(), file.trk.len()), (1, 0)); + assert_eq!(file.rte[0].seg.len(), 1); + assert_eq!(file.rte[0].seg[0].anchor, Some(0)); + } } diff --git a/gpx-rs/src/engine/command/file/sync.rs b/gpx-rs/src/engine/command/file/sync.rs index ee297712e..17611a56f 100644 --- a/gpx-rs/src/engine/command/file/sync.rs +++ b/gpx-rs/src/engine/command/file/sync.rs @@ -80,6 +80,7 @@ mod tests { New { name, trackpoint: None, + route: false, } .apply(&mut fx.state()) .unwrap(); diff --git a/gpx-rs/src/engine/command/tools/new_waypoint.rs b/gpx-rs/src/engine/command/tools/new_waypoint.rs index 906a343c9..6ae5ecaff 100644 --- a/gpx-rs/src/engine/command/tools/new_waypoint.rs +++ b/gpx-rs/src/engine/command/tools/new_waypoint.rs @@ -119,12 +119,14 @@ mod tests { New { name: "a", trackpoint: None, + route: false, } .apply(&mut fx.state()) .unwrap(); New { name: "b", trackpoint: None, + route: false, } .apply(&mut fx.state()) .unwrap(); @@ -170,6 +172,7 @@ mod tests { New { name: "a", trackpoint: None, + route: false, } .apply(&mut fx.state()) .unwrap(); @@ -197,6 +200,7 @@ mod tests { New { name, trackpoint: None, + route: false, } .apply(&mut fx.state()) .unwrap(); @@ -235,6 +239,7 @@ mod tests { New { name: "a", trackpoint: None, + route: false, } .apply(&mut fx.state()) .unwrap(); @@ -251,6 +256,7 @@ mod tests { New { name: "a", trackpoint: None, + route: false, } .apply(&mut fx.state()) .unwrap(); diff --git a/gpx-rs/src/engine/tests.rs b/gpx-rs/src/engine/tests.rs index 9100a4619..516977def 100644 --- a/gpx-rs/src/engine/tests.rs +++ b/gpx-rs/src/engine/tests.rs @@ -87,6 +87,7 @@ fn new(engine: &mut TestEngine, name: &str) -> bool { Command::New(New { name, trackpoint: None, + route: false, }), ) } @@ -1489,6 +1490,7 @@ mod per_file_history { .execute(Action::Edit(Command::New(New { name, trackpoint: None, + route: false, }))) .unwrap(); *engine.order().last().unwrap() diff --git a/tauri/src/commands/files.rs b/tauri/src/commands/files.rs index 2634fb4ca..ae25d6bc5 100644 --- a/tauri/src/commands/files.rs +++ b/tauri/src/commands/files.rs @@ -16,10 +16,16 @@ pub fn new_file( lng: Option, lat: Option, ele: Option, + route: Option, folder: Option, ) -> api::Outcome { + let route = route.unwrap_or_default(); // in `folder` if it is given, otherwise like the selected file, otherwise in the open folder - state.core(move |core| core.creating(folder, true, |e| api::new_file(e, &name, lng, lat, ele))) + state.core(move |core| { + core.creating(folder, true, |e| { + api::new_file(e, &name, lng, lat, ele, route) + }) + }) } /// The files are in the body, one after the other, the headers `lengths` and `names` (JSON, diff --git a/tauri/src/tests.rs b/tauri/src/tests.rs index 56421842a..69a5f05af 100644 --- a/tauri/src/tests.rs +++ b/tauri/src/tests.rs @@ -483,7 +483,7 @@ fn files_made_from_a_file_of_the_open_folder_are_written_next_to_it_at_once() { assert_eq!(opened.added().len(), 1); let copy = core.creating(None, false, gpx_engine::api::duplicate); let fresh = core.creating(None, true, |e| { - gpx_engine::api::new_file(e, "fresh", None, None, None) + gpx_engine::api::new_file(e, "fresh", None, None, None, false) }); // a copy of the file goes next to it, a new file with nothing selected in the selection // of the file that was just made diff --git a/tauri/src/workspace.rs b/tauri/src/workspace.rs index 8801acc84..fcf4d11dd 100644 --- a/tauri/src/workspace.rs +++ b/tauri/src/workspace.rs @@ -1247,7 +1247,7 @@ mod tests { #[test] fn a_file_that_is_not_on_the_disk_is_unsaved_until_it_is_given_a_place() { let mut fx = Fixture::new(); - api::new_file(&mut fx.engine, "fresh", None, None, None); + api::new_file(&mut fx.engine, "fresh", None, None, None, false); let id = fx.ids()[0]; assert!(fx.workspace.is_dirty(&fx.engine, id)); assert_eq!( @@ -1272,9 +1272,9 @@ mod tests { fn several_files_without_a_place_go_in_a_folder_with_names_that_are_free() { let mut fx = Fixture::new(); fx.write("fresh.gpx", "already there"); - api::new_file(&mut fx.engine, "fresh", None, None, None); - api::new_file(&mut fx.engine, "a/b: c", None, None, None); - api::new_file(&mut fx.engine, "fresh", None, None, None); + api::new_file(&mut fx.engine, "fresh", None, None, None, false); + api::new_file(&mut fx.engine, "a/b: c", None, None, None, false); + api::new_file(&mut fx.engine, "fresh", None, None, None, false); let ids = fx.ids(); let folder = fx.folder.clone(); fx.workspace @@ -1697,7 +1697,7 @@ mod tests { fx.open_folder(); let a = fx.ids()[0]; fx.rename(a, "edited"); - api::new_file(&mut fx.engine, "fresh", None, None, None); + api::new_file(&mut fx.engine, "fresh", None, None, None, false); let fresh = fx.id_named("fresh"); fx.workspace.close_files(&mut fx.engine, &[a, fresh], true); assert!(fx.ids().is_empty()); @@ -1713,7 +1713,7 @@ mod tests { let mut fx = Fixture::new(); fx.write("a.gpx", "a"); fx.open_folder(); - api::new_file(&mut fx.engine, "fresh", None, None, None); + api::new_file(&mut fx.engine, "fresh", None, None, None, false); assert_eq!(fx.ids().len(), 2); // the new file has nowhere to go: it has to be discarded diff --git a/wasm/src/command/files.rs b/wasm/src/command/files.rs index e891502d2..1cb204f62 100644 --- a/wasm/src/command/files.rs +++ b/wasm/src/command/files.rs @@ -10,11 +10,18 @@ use crate::ts::*; // File commands -/// Creates a file and selects it. With `lng` and `lat`, it starts with a track and a segment that -/// hold that trackpoint (at `ele`, 0 by default). +/// Creates a file and selects it. With `route`, it starts with a route. With `lng` and `lat`, it +/// starts with a segment that holds that trackpoint (at `ele`, 0 by default): the one of its route +/// with `route`, of a track otherwise. #[wasm_bindgen] -pub fn new_file(name: &str, lng: Option, lat: Option, ele: Option) -> Outcome { - run(|e| api::new_file(e, name, lng, lat, ele)) +pub fn new_file( + name: &str, + lng: Option, + lat: Option, + ele: Option, + route: bool, +) -> Outcome { + run(|e| api::new_file(e, name, lng, lat, ele, route)) } /// Loads files as a single command (one undo step). The files are in `data`, one after the diff --git a/wasm/src/tests.rs b/wasm/src/tests.rs index 276196156..88d1660bd 100644 --- a/wasm/src/tests.rs +++ b/wasm/src/tests.rs @@ -84,7 +84,7 @@ fn uuid_bytes(ids: &[String]) -> Vec { fn test_new_file_is_listed_and_selected() { start(); assert!(run(crate::command::files::new_file( - "route", None, None, None + "route", None, None, None, false ))); assert_eq!(last_error(), None); @@ -198,7 +198,9 @@ fn test_the_reason_of_a_failure_can_be_read() { assert!(!run(crate::command::tools::reverse())); assert_eq!(last_error().as_deref(), Some("nothing to do")); // the next call starts afresh - assert!(run(crate::command::files::new_file("a", None, None, None))); + assert!(run(crate::command::files::new_file( + "a", None, None, None, false + ))); assert_eq!(last_error(), None); // invalid data @@ -251,7 +253,9 @@ fn test_the_reason_of_a_failure_can_be_read() { assert!(last_error().is_some()); // answers are not failures - assert!(run(crate::command::files::new_file("b", None, None, None))); + assert!(run(crate::command::files::new_file( + "b", None, None, None, false + ))); assert!(!crate::command::files::can_paste()); assert_eq!(last_error(), None); } @@ -260,7 +264,9 @@ fn test_the_reason_of_a_failure_can_be_read() { fn test_undo_and_redo() { started_with(&[]); assert!(!can_undo() && !can_redo()); - assert!(run(crate::command::files::new_file("a", None, None, None))); + assert!(run(crate::command::files::new_file( + "a", None, None, None, false + ))); assert!(can_undo() && !can_redo()); assert!(run(undo())); assert!(order().is_empty()); @@ -386,7 +392,7 @@ fn test_move_elements_takes_js_objects() { fn test_waypoints() { started_with(&[]); assert!(run(crate::command::files::new_file( - "file", None, None, None + "file", None, None, None, false ))); let file = order().remove(0); assert!(run(crate::command::waypoints::new_waypoint( @@ -490,7 +496,9 @@ fn test_editing_tools_change_the_statistics() { #[wasm_bindgen_test] fn test_last_update_describes_the_last_call_only() { started_with(&[]); - assert!(run(crate::command::files::new_file("a", None, None, None))); + assert!(run(crate::command::files::new_file( + "a", None, None, None, false + ))); let update = last_outcome(); assert_eq!(array(get(&update, "added")).length(), 1); assert_eq!(get(&update, "orderChanged").as_bool(), Some(true)); @@ -502,7 +510,9 @@ fn test_last_update_describes_the_last_call_only() { assert_eq!(get(&update, "orderChanged").as_bool(), Some(false)); assert_eq!(get(&update, "selectionChanged").as_bool(), Some(false)); - assert!(run(crate::command::files::new_file("b", None, None, None))); + assert!(run(crate::command::files::new_file( + "b", None, None, None, false + ))); assert!(!run(crate::command::tools::crop(3, 1))); let update = last_outcome(); assert_eq!(array(get(&update, "added")).length(), 0); diff --git a/website/src/lib/actions/file-actions.ts b/website/src/lib/actions/file-actions.ts index 9e812cdad..40a8e491a 100644 --- a/website/src/lib/actions/file-actions.ts +++ b/website/src/lib/actions/file-actions.ts @@ -20,6 +20,12 @@ export function createFile() { currentTool.set(Tool.ROUTING); } +/** Creates a file that starts with an empty route, which the routing tool then draws. */ +export function createRouteFile() { + engine.newFile(newFileName(), undefined, true); + currentTool.set(Tool.ROUTING); +} + /** Asks for the files to open: with the file picker of the system in the desktop app. */ export async function openFiles() { if (get(engine.workspace)) { diff --git a/website/src/lib/components/Menu.svelte b/website/src/lib/components/Menu.svelte index 92df6e68c..f811c91aa 100644 --- a/website/src/lib/components/Menu.svelte +++ b/website/src/lib/components/Menu.svelte @@ -68,6 +68,7 @@ closeFiles, closeFolder, createFile, + createRouteFile, loadFiles, openFiles, openFolder, @@ -160,9 +161,13 @@ - {i18n._('menu.new')} + {i18n._('menu.new_file')} + + + {i18n._('menu.new_route_file')} + diff --git a/website/src/lib/components/explorer/ExplorerRow.svelte b/website/src/lib/components/explorer/ExplorerRow.svelte index 78a701b46..dbf1d4d77 100644 --- a/website/src/lib/components/explorer/ExplorerRow.svelte +++ b/website/src/lib/components/explorer/ExplorerRow.svelte @@ -116,12 +116,16 @@ /** The folder where what is made from the menu goes: the folder of the row. */ let folder = $derived(kind === 'file' ? undefined : path); - /** Asks for the name of a file or a folder to make in the folder of the row (see `creating`). */ - function create(what: 'file' | 'folder') { + /** + * Asks for the name of a file or a folder to make in the folder of the row (see `creating`). + * With `route`, the file starts with an empty route. + */ + function create(what: 'file' | 'folder', route = false) { if (folder === undefined) return; // where what is being named is shown folders.open(folder); creating.kind = what; + creating.route = route; creating.parent = folder; } @@ -286,6 +290,10 @@ {i18n._('menu.explorer_menu.new_file')} + create('file', true)}> + + {i18n._('menu.explorer_menu.new_route_file')} + create('folder')}> {i18n._('menu.explorer_menu.new_folder')} diff --git a/website/src/lib/components/explorer/ExplorerTree.svelte b/website/src/lib/components/explorer/ExplorerTree.svelte index 5527ba991..2819b53c4 100644 --- a/website/src/lib/components/explorer/ExplorerTree.svelte +++ b/website/src/lib/components/explorer/ExplorerTree.svelte @@ -1,6 +1,6 @@