agent: Add assistant panel width persistence (#28808)

Previously, the assistant panel width was not persisted across sessions.
This meant that upon restarting the Zed editor, the panel would revert
to its default size, disrupting the user's preferred layout.

This pull request introduces persistence for the assistant panel width.
The width is now saved to the key-value store when the editor is closed
and restored on startup, ensuring a consistent UI experience across
different sessions.

Release Notes:

- agent: Add assistant panel width persistence

---------

Signed-off-by: Umesh Yadav <umesh4257@gmail.com>
This commit is contained in:
Umesh Yadav 2025-05-03 01:35:03 +05:30 committed by GitHub
parent da98e300cc
commit c918f6cde1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -3,6 +3,9 @@ use std::path::Path;
use std::sync::Arc; use std::sync::Arc;
use std::time::Duration; use std::time::Duration;
use db::kvp::KEY_VALUE_STORE;
use serde::{Deserialize, Serialize};
use anyhow::{Result, anyhow}; use anyhow::{Result, anyhow};
use assistant_context_editor::{ use assistant_context_editor::{
AssistantContext, AssistantPanelDelegate, ConfigurationError, ContextEditor, ContextEvent, AssistantContext, AssistantPanelDelegate, ConfigurationError, ContextEditor, ContextEvent,
@ -53,6 +56,13 @@ use crate::{
ToggleContextPicker, ToggleNavigationMenu, ToggleOptionsMenu, ToggleContextPicker, ToggleNavigationMenu, ToggleOptionsMenu,
}; };
const AGENT_PANEL_KEY: &str = "agent_panel";
#[derive(Serialize, Deserialize)]
struct SerializedAssistantPanel {
width: Option<Pixels>,
}
pub fn init(cx: &mut App) { pub fn init(cx: &mut App) {
cx.observe_new( cx.observe_new(
|workspace: &mut Workspace, _window, _cx: &mut Context<Workspace>| { |workspace: &mut Workspace, _window, _cx: &mut Context<Workspace>| {
@ -302,9 +312,22 @@ pub struct AssistantPanel {
assistant_navigation_menu: Option<Entity<ContextMenu>>, assistant_navigation_menu: Option<Entity<ContextMenu>>,
width: Option<Pixels>, width: Option<Pixels>,
height: Option<Pixels>, height: Option<Pixels>,
pending_serialization: Option<Task<Result<()>>>,
} }
impl AssistantPanel { impl AssistantPanel {
fn serialize(&mut self, cx: &mut Context<Self>) {
let width = self.width;
self.pending_serialization = Some(cx.background_spawn(async move {
KEY_VALUE_STORE
.write_kvp(
AGENT_PANEL_KEY.into(),
serde_json::to_string(&SerializedAssistantPanel { width })?,
)
.await?;
anyhow::Ok(())
}));
}
pub fn load( pub fn load(
workspace: WeakEntity<Workspace>, workspace: WeakEntity<Workspace>,
prompt_builder: Arc<PromptBuilder>, prompt_builder: Arc<PromptBuilder>,
@ -343,8 +366,19 @@ impl AssistantPanel {
})? })?
.await?; .await?;
workspace.update_in(cx, |workspace, window, cx| { let serialized_panel = if let Some(panel) = cx
cx.new(|cx| { .background_spawn(async move { KEY_VALUE_STORE.read_kvp(AGENT_PANEL_KEY) })
.await
.log_err()
.flatten()
{
Some(serde_json::from_str::<SerializedAssistantPanel>(&panel)?)
} else {
None
};
let panel = workspace.update_in(cx, |workspace, window, cx| {
let panel = cx.new(|cx| {
Self::new( Self::new(
workspace, workspace,
thread_store, thread_store,
@ -353,8 +387,17 @@ impl AssistantPanel {
window, window,
cx, cx,
) )
}) });
}) if let Some(serialized_panel) = serialized_panel {
panel.update(cx, |panel, cx| {
panel.width = serialized_panel.width.map(|w| w.round());
cx.notify();
});
}
panel
})?;
Ok(panel)
}) })
} }
@ -586,6 +629,7 @@ impl AssistantPanel {
assistant_navigation_menu: None, assistant_navigation_menu: None,
width: None, width: None,
height: None, height: None,
pending_serialization: None,
} }
} }
@ -1209,6 +1253,7 @@ impl Panel for AssistantPanel {
DockPosition::Left | DockPosition::Right => self.width = size, DockPosition::Left | DockPosition::Right => self.width = size,
DockPosition::Bottom => self.height = size, DockPosition::Bottom => self.height = size,
} }
self.serialize(cx);
cx.notify(); cx.notify();
} }