Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clear all blueprints in RAM and on disk when clicking "Reset Viewer" #5199

Merged
merged 4 commits into from
Feb 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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(())
}
}