Simplify ListState API (#35685)

Follow up to: https://github.com/zed-industries/zed/pull/35670,
simplifies the List state APIs so you no longer have to worry about
strong vs. weak pointers when rendering list items.

Release Notes:

- N/A

---------

Co-authored-by: Agus Zubiaga <agus@zed.dev>
This commit is contained in:
Mikayla Maki 2025-08-05 17:02:26 -07:00 committed by GitHub
parent d0de81b0b4
commit 53175263a1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 322 additions and 403 deletions

View file

@ -173,23 +173,7 @@ impl AcpThreadView {
let mention_set = mention_set.clone();
let list_state = ListState::new(0, gpui::ListAlignment::Bottom, px(2048.0), {
let this = cx.entity().downgrade();
move |index: usize, window, cx| {
let Some(this) = this.upgrade() else {
return Empty.into_any();
};
this.update(cx, |this, cx| {
let Some((entry, len)) = this.thread().and_then(|thread| {
let entries = &thread.read(cx).entries();
Some((entries.get(index)?, entries.len()))
}) else {
return Empty.into_any();
};
this.render_entry(index, len, entry, window, cx)
})
}
});
let list_state = ListState::new(0, gpui::ListAlignment::Bottom, px(2048.0));
Self {
agent: agent.clone(),
@ -2552,10 +2536,21 @@ impl Render for AcpThreadView {
v_flex().flex_1().map(|this| {
if self.list_state.item_count() > 0 {
this.child(
list(self.list_state.clone())
.with_sizing_behavior(gpui::ListSizingBehavior::Auto)
.flex_grow()
.into_any(),
list(
self.list_state.clone(),
cx.processor(|this, index: usize, window, cx| {
let Some((entry, len)) = this.thread().and_then(|thread| {
let entries = &thread.read(cx).entries();
Some((entries.get(index)?, entries.len()))
}) else {
return Empty.into_any();
};
this.render_entry(index, len, entry, window, cx)
}),
)
.with_sizing_behavior(gpui::ListSizingBehavior::Auto)
.flex_grow()
.into_any(),
)
.children(match thread_clone.read(cx).status() {
ThreadStatus::Idle | ThreadStatus::WaitingForToolConfirmation => {

View file

@ -780,13 +780,7 @@ impl ActiveThread {
cx.observe_global::<SettingsStore>(|_, cx| cx.notify()),
];
let list_state = ListState::new(0, ListAlignment::Bottom, px(2048.), {
let this = cx.entity().downgrade();
move |ix, window: &mut Window, cx: &mut App| {
this.update(cx, |this, cx| this.render_message(ix, window, cx))
.unwrap()
}
});
let list_state = ListState::new(0, ListAlignment::Bottom, px(2048.));
let workspace_subscription = if let Some(workspace) = workspace.upgrade() {
Some(cx.observe_release(&workspace, |this, _, cx| {
@ -1846,7 +1840,12 @@ impl ActiveThread {
)))
}
fn render_message(&self, ix: usize, window: &mut Window, cx: &mut Context<Self>) -> AnyElement {
fn render_message(
&mut self,
ix: usize,
window: &mut Window,
cx: &mut Context<Self>,
) -> AnyElement {
let message_id = self.messages[ix];
let workspace = self.workspace.clone();
let thread = self.thread.read(cx);
@ -3613,7 +3612,7 @@ impl Render for ActiveThread {
this.hide_scrollbar_later(cx);
}),
)
.child(list(self.list_state.clone()).flex_grow())
.child(list(self.list_state.clone(), cx.processor(Self::render_message)).flex_grow())
.when_some(self.render_vertical_scrollbar(cx), |this, scrollbar| {
this.child(scrollbar)
})

View file

@ -1471,7 +1471,6 @@ impl AgentPanel {
let current_is_special = current_is_history || current_is_config;
let new_is_special = new_is_history || new_is_config;
let mut old_acp_thread = None;
match &self.active_view {
ActiveView::Thread { thread, .. } => {
@ -1483,9 +1482,6 @@ impl AgentPanel {
});
}
}
ActiveView::ExternalAgentThread { thread_view } => {
old_acp_thread.replace(thread_view.downgrade());
}
_ => {}
}
@ -1516,11 +1512,6 @@ impl AgentPanel {
self.active_view = new_view;
}
debug_assert!(
old_acp_thread.map_or(true, |thread| !thread.is_upgradable()),
"AcpThreadView leaked"
);
self.acp_message_history.borrow_mut().reset_position();
self.focus_handle(cx).focus(window);