Skip to content

Commit

Permalink
Clear all blueprints in RAM and on disk when clicking "Reset Viewer" (#…
Browse files Browse the repository at this point in the history
…5199)

### What
* Closes #4164

### Checklist
* [x] I have read and agree to [Contributor
Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and
the [Code of
Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md)
* [x] I've included a screenshot or gif (if applicable)
* [x] I have tested the web demo (if applicable):
* Using newly built examples:
[app.rerun.io](https://app.rerun.io/pr/5199/index.html)
* Using examples from latest `main` build:
[app.rerun.io](https://app.rerun.io/pr/5199/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json)
* Using full set of examples from `nightly` build:
[app.rerun.io](https://app.rerun.io/pr/5199/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json)
* [x] The PR title and labels are set such as to maximize their
usefulness for the next release's CHANGELOG
* [x] If applicable, add a new check to the [release
checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)!

- [PR Build Summary](https://build.rerun.io/pr/5199)
- [Docs
preview](https://rerun.io/preview/6693fc4968ffb24bd89e262b25ef06ac9d171576/docs)
<!--DOCS-PREVIEW-->
- [Examples
preview](https://rerun.io/preview/6693fc4968ffb24bd89e262b25ef06ac9d171576/examples)
<!--EXAMPLES-PREVIEW-->
- [Recent benchmark results](https://build.rerun.io/graphs/crates.html)
- [Wasm size tracking](https://build.rerun.io/graphs/sizes.html)
  • Loading branch information
emilk authored Feb 15, 2024
1 parent 4dc75b8 commit 5c7dabe
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 37 deletions.
2 changes: 1 addition & 1 deletion crates/re_ui/src/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ impl UICommand {

Self::ResetViewer => (
"Reset Viewer",
"Reset the Viewer to how it looked the first time you ran it",
"Reset the Viewer to how it looked the first time you ran it, forgetting all stored blueprints and UI state",
),

#[cfg(not(target_arch = "wasm32"))]
Expand Down
1 change: 1 addition & 0 deletions crates/re_viewer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ web-sys = { workspace = true, features = [
'Url',
'UrlSearchParams',
'Window',
"Storage",
] }


Expand Down
11 changes: 8 additions & 3 deletions crates/re_viewer/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,7 @@ impl App {
// By clearing the blueprint it will be re-populated with the defaults
// at the beginning of the next frame.
re_log::debug!("Reset blueprint");
store_hub.clear_blueprint();
store_hub.clear_current_blueprint();
}
SystemCommand::UpdateBlueprint(blueprint_id, updates) => {
// We only want to update the blueprint if the "inspect blueprint timeline" mode is
Expand Down Expand Up @@ -1048,12 +1048,17 @@ impl App {
/// Reset the viewer to how it looked the first time you ran it.
fn reset(&mut self, store_hub: &mut StoreHub, egui_ctx: &egui::Context) {
self.state = Default::default();
store_hub.clear_blueprint();

// Keep the style:
store_hub.clear_all_blueprints();

// Reset egui, but keep the style:
let style = egui_ctx.style();
egui_ctx.memory_mut(|mem| *mem = Default::default());
egui_ctx.set_style((*style).clone());

if let Err(err) = crate::reset_viewer_persistence() {
re_log::warn!("Failed to reset viewer: {err}");
}
}

pub fn recording_db(&self) -> Option<&EntityDb> {
Expand Down
48 changes: 48 additions & 0 deletions crates/re_viewer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -234,3 +234,51 @@ pub fn wake_up_ui_thread_on_each_msg<T: Send + 'static>(
.unwrap();
new_rx
}

/// Reset the viewer state as stored on disk and local storage,
/// keeping only the analytics state.
#[allow(clippy::unnecessary_wraps)] // wasm only
pub fn reset_viewer_persistence() -> anyhow::Result<()> {
#[cfg(not(target_arch = "wasm32"))]
{
let Some(data_dir) = eframe::storage_dir(native::APP_ID) else {
anyhow::bail!("Failed to figure out where Rerun stores its data.")
};

// Note: `remove_dir_all` fails if the directory doesn't exist.
if data_dir.exists() {
// Keep analytics, because it is used to uniquely identify users over time.
let analytics_file_path = data_dir.join("analytics.json");
let analytics = std::fs::read(&analytics_file_path);

if let Err(err) = std::fs::remove_dir_all(&data_dir) {
anyhow::bail!("Failed to remove {data_dir:?}: {err}");
} else {
re_log::info!("Cleared {data_dir:?}.");
}

if let Ok(analytics) = analytics {
// Restore analytics.json:
std::fs::create_dir(&data_dir).ok();
std::fs::write(&analytics_file_path, analytics).ok();
}
} else {
re_log::info!("Rerun state was already cleared.");
}
}
#[cfg(target_arch = "wasm32")]
{
// TODO(emilk): eframe should have an API for this.
if let Some(storage) = web_sys::window()
.and_then(|w| w.local_storage().ok())
.flatten()
{
storage.delete("egui_memory_ron").ok();
storage.delete(eframe::APP_KEY).ok();
}

// TODO(#2579): implement web-storage for blueprints as well, and clear it here
}

Ok(())
}
9 changes: 8 additions & 1 deletion crates/re_viewer/src/store_hub.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,14 +186,21 @@ impl StoreHub {
}

/// Clear the current blueprint
pub fn clear_blueprint(&mut self) {
pub fn clear_current_blueprint(&mut self) {
if let Some(app_id) = &self.selected_application_id {
if let Some(blueprint_id) = self.blueprint_by_app_id.remove(app_id) {
self.store_bundle.remove(&blueprint_id);
}
}
}

/// Forgets all blueprints
pub fn clear_all_blueprints(&mut self) {
for (_app_id, blueprint_id) in self.blueprint_by_app_id.drain() {
self.store_bundle.remove(&blueprint_id);
}
}

/// Insert a new recording into the [`StoreHub`].
///
/// Note that the recording is not automatically made active. Use [`StoreHub::set_recording_id`]
Expand Down
33 changes: 1 addition & 32 deletions crates/rerun/src/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,7 @@ where
Command::Print(print_command) => print_command.run(),

#[cfg(feature = "native_viewer")]
Command::Reset => reset_viewer(),
Command::Reset => re_viewer::reset_viewer_persistence(),
}
} else {
run_impl(build_info, call_source, args).await
Expand Down Expand Up @@ -880,34 +880,3 @@ fn parse_max_latency(max_latency: Option<&String>) -> f32 {
.unwrap_or_else(|err| panic!("Failed to parse max_latency ({max_latency:?}): {err}"))
})
}

#[cfg(feature = "native_viewer")]
fn reset_viewer() -> anyhow::Result<()> {
let Some(data_dir) = re_viewer::external::eframe::storage_dir(re_viewer::native::APP_ID) else {
anyhow::bail!("Failed to figure out where Rerun stores its data.")
};

// Note: `remove_dir_all` fails if the directory doesn't exist.
if data_dir.exists() {
// Keep analytics, because it is used to uniquely identify users over time.
let analytics_file_path = data_dir.join("analytics.json");
let analytics = std::fs::read(&analytics_file_path);

if let Err(err) = std::fs::remove_dir_all(&data_dir) {
anyhow::bail!("Failed to remove {data_dir:?}: {err}");
} else {
eprintln!("Cleared {data_dir:?}.");
}

if let Ok(analytics) = analytics {
// Restore analytics.json:
std::fs::create_dir(&data_dir).ok();
std::fs::write(&analytics_file_path, analytics).ok();
}

Ok(())
} else {
eprintln!("Rerun state was already cleared.");
Ok(())
}
}

0 comments on commit 5c7dabe

Please sign in to comment.