From 33f0291f6d055227c55fc5cd30ca4f32fb43589c Mon Sep 17 00:00:00 2001 From: Jason Lee Date: Mon, 9 Sep 2024 14:03:51 +0800 Subject: [PATCH] Improve layout save details for example app. --- crates/app/src/main.rs | 2 +- crates/app/src/story_workspace.rs | 54 +++++++++++++++++++++++++------ crates/ui/src/dock/mod.rs | 9 +++--- crates/ui/src/dock/panel.rs | 4 +-- 4 files changed, 53 insertions(+), 16 deletions(-) diff --git a/crates/app/src/main.rs b/crates/app/src/main.rs index 752e088e..41027bc1 100644 --- a/crates/app/src/main.rs +++ b/crates/app/src/main.rs @@ -1,4 +1,4 @@ -use std::{sync::Arc, thread}; +use std::sync::Arc; use anyhow::Result; use app_state::AppState; diff --git a/crates/app/src/story_workspace.rs b/crates/app/src/story_workspace.rs index 2d47df69..8be51155 100644 --- a/crates/app/src/story_workspace.rs +++ b/crates/app/src/story_workspace.rs @@ -2,7 +2,7 @@ use anyhow::Result; use gpui::*; use prelude::FluentBuilder as _; use private::serde::Deserialize; -use std::sync::Arc; +use std::{sync::Arc, time::Duration}; use story::{ ButtonStory, CalendarStory, DropdownStory, IconStory, ImageStory, InputStory, ListStory, ModalStory, PopupStory, ProgressStory, ResizableStory, ScrollableStory, StoryContainer, @@ -42,6 +42,8 @@ pub struct StoryWorkspace { dock_area: View, locale_selector: View, theme_color_picker: View, + last_layout_state: Option, + _save_layout_task: Option>, } impl StoryWorkspace { @@ -64,15 +66,19 @@ impl StoryWorkspace { dock_area.update(cx, |view, cx| view.set_root(dock_item, cx)); - cx.subscribe(&dock_area, |_, dock_area, ev: &DockEvent, cx| match ev { - DockEvent::LayoutChanged => { - // Make debounce + cx.subscribe(&dock_area, |this, dock_area, ev: &DockEvent, cx| match ev { + DockEvent::LayoutChanged => this.save_layout(dock_area, cx), + }) + .detach(); - println!("Saving layout..."); - let json = dock_area.read(cx).dump(cx).unwrap(); - // Save layout json to app dir layout.json - std::fs::write("layout.json", json).unwrap(); - } + let dock_area1 = dock_area.clone(); + cx.on_app_quit(move |cx| { + let state = dock_area1.read(cx).dump(cx); + + cx.background_executor().spawn(async move { + // Save layout before quitting + Self::save_state(&state).unwrap(); + }) }) .detach(); @@ -106,9 +112,39 @@ impl StoryWorkspace { dock_area, locale_selector, theme_color_picker, + last_layout_state: None, + _save_layout_task: None, } } + fn save_layout(&mut self, dock_area: View, cx: &mut ViewContext) { + self._save_layout_task = Some(cx.spawn(|this, mut cx| async move { + Timer::after(Duration::from_secs(1)).await; + + let _ = cx.update(|cx| { + let dock_area = dock_area.read(cx); + let state = dock_area.dump(cx); + + let last_layout_state = this.upgrade().unwrap().read(cx).last_layout_state.clone(); + if Some(&state) == last_layout_state.as_ref() { + return; + } + + Self::save_state(&state).unwrap(); + let _ = this.update(cx, |this, _| { + this.last_layout_state = Some(state); + }); + }); + })); + } + + fn save_state(state: &DockItemState) -> Result<()> { + println!("Save layout..."); + let json = serde_json::to_string(state)?; + std::fs::write("layout.json", json)?; + Ok(()) + } + fn load_layout(dock_area: &WeakView, cx: &mut WindowContext) -> Result { let fname = "layout.json"; let json = std::fs::read_to_string(fname)?; diff --git a/crates/ui/src/dock/mod.rs b/crates/ui/src/dock/mod.rs index 02a613f6..ae96bc41 100644 --- a/crates/ui/src/dock/mod.rs +++ b/crates/ui/src/dock/mod.rs @@ -191,11 +191,12 @@ impl DockArea { cx.notify(); } - /// Dump the dock panels layout to JSON string. - pub fn dump(&self, cx: &AppContext) -> Result { + /// Dump the dock panels layout to DockItemState. + /// + /// See also `DockItemState::to_item` for the load DockItem from DockItemState. + pub fn dump(&self, cx: &AppContext) -> DockItemState { let root = self.items.view(); - let state = root.dump(cx); - serde_json::to_string_pretty(&state) + root.dump(cx) } /// Subscribe event on the panels diff --git a/crates/ui/src/dock/panel.rs b/crates/ui/src/dock/panel.rs index ee86a000..2f459e65 100644 --- a/crates/ui/src/dock/panel.rs +++ b/crates/ui/src/dock/panel.rs @@ -111,14 +111,14 @@ impl PartialEq for dyn PanelView { } } -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] pub struct DockItemState { pub panel_name: String, pub children: Vec, pub info: DockItemInfo, } -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub enum DockItemInfo { #[serde(rename = "stack")] Stack {