sidebar: Sort threads by created time (#51193)

Release Notes:

- N/A
This commit is contained in:
Danilo Leal 2026-03-10 12:22:01 -03:00 committed by GitHub
parent d18e4a75bc
commit eae21de630
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 32 additions and 7 deletions

View file

@ -242,6 +242,7 @@ pub struct AgentSessionInfo {
pub cwd: Option<PathBuf>,
pub title: Option<SharedString>,
pub updated_at: Option<DateTime<Utc>>,
pub created_at: Option<DateTime<Utc>>,
pub meta: Option<acp::Meta>,
}
@ -252,6 +253,7 @@ impl AgentSessionInfo {
cwd: None,
title: None,
updated_at: None,
created_at: None,
meta: None,
}
}

View file

@ -45,6 +45,7 @@ impl From<&DbThreadMetadata> for acp_thread::AgentSessionInfo {
cwd: None,
title: Some(meta.title.clone()),
updated_at: Some(meta.updated_at),
created_at: meta.created_at,
meta: None,
}
}
@ -482,7 +483,10 @@ impl ThreadsDatabase {
let data_type = DataType::Zstd;
let data = compressed;
let created_at = Utc::now().to_rfc3339();
// Use the thread's updated_at as created_at for new threads.
// This ensures the creation time reflects when the thread was conceptually
// created, not when it was saved to the database.
let created_at = updated_at.clone();
let mut insert = connection.exec_bound::<(Arc<str>, Option<Arc<str>>, Option<String>, Option<String>, String, String, DataType, Vec<u8>, String)>(indoc! {"
INSERT INTO threads (id, parent_id, folder_paths, folder_paths_order, summary, updated_at, data_type, data, created_at)

View file

@ -131,6 +131,7 @@ impl AgentSessionList for AcpSessionList {
.ok()
.map(|dt| dt.with_timezone(&chrono::Utc))
}),
created_at: None,
meta: s.meta,
})
.collect(),

View file

@ -1232,6 +1232,7 @@ mod tests {
cwd: None,
title: Some(title.to_string().into()),
updated_at: None,
created_at: None,
meta: None,
}
}
@ -1443,6 +1444,7 @@ mod tests {
cwd: None,
title: Some("Original Title".into()),
updated_at: None,
created_at: None,
meta: None,
}];
let session_list = Rc::new(TestSessionList::new(sessions));
@ -1479,6 +1481,7 @@ mod tests {
cwd: None,
title: Some("Original Title".into()),
updated_at: None,
created_at: None,
meta: None,
}];
let session_list = Rc::new(TestSessionList::new(sessions));
@ -1512,6 +1515,7 @@ mod tests {
cwd: None,
title: Some("Original Title".into()),
updated_at: None,
created_at: None,
meta: None,
}];
let session_list = Rc::new(TestSessionList::new(sessions));
@ -1548,6 +1552,7 @@ mod tests {
cwd: None,
title: None,
updated_at: None,
created_at: None,
meta: None,
}];
let session_list = Rc::new(TestSessionList::new(sessions));
@ -1588,6 +1593,7 @@ mod tests {
cwd: None,
title: Some("Server Title".into()),
updated_at: None,
created_at: None,
meta: None,
}];
let session_list = Rc::new(TestSessionList::new(sessions));
@ -1625,6 +1631,7 @@ mod tests {
cwd: None,
title: Some("Original".into()),
updated_at: None,
created_at: None,
meta: None,
}];
let session_list = Rc::new(TestSessionList::new(sessions));

View file

@ -63,6 +63,7 @@ impl From<&ActiveThreadInfo> for acp_thread::AgentSessionInfo {
cwd: None,
title: Some(info.title.clone()),
updated_at: Some(Utc::now()),
created_at: Some(Utc::now()),
meta: None,
}
}
@ -512,7 +513,13 @@ impl Sidebar {
}
}
threads.sort_by(|a, b| b.session_info.updated_at.cmp(&a.session_info.updated_at));
// Sort by created_at (newest first), falling back to updated_at
// for threads without a created_at (e.g., ACP sessions).
threads.sort_by(|a, b| {
let a_time = a.session_info.created_at.or(a.session_info.updated_at);
let b_time = b.session_info.created_at.or(b.session_info.updated_at);
b_time.cmp(&a_time)
});
}
if !query.is_empty() {
@ -726,12 +733,9 @@ impl Sidebar {
} => self.render_new_thread(ix, path_list, workspace, is_selected, cx),
};
// add the blue border here, not in the sub methods
if is_group_header_after_first {
v_flex()
.w_full()
.pt_2()
.border_t_1()
.border_color(cx.theme().colors().border_variant)
.child(rendered)
@ -1472,9 +1476,9 @@ impl Render for Sidebar {
.child(
h_flex()
.flex_none()
.p_2()
.px_2p5()
.h(Tab::container_height(cx))
.gap_1p5()
.gap_2()
.border_b_1()
.border_color(cx.theme().colors().border)
.child(
@ -2017,6 +2021,7 @@ mod tests {
cwd: None,
title: Some("Completed thread".into()),
updated_at: Some(Utc::now()),
created_at: Some(Utc::now()),
meta: None,
},
icon: IconName::ZedAgent,
@ -2034,6 +2039,7 @@ mod tests {
cwd: None,
title: Some("Running thread".into()),
updated_at: Some(Utc::now()),
created_at: Some(Utc::now()),
meta: None,
},
icon: IconName::ZedAgent,
@ -2051,6 +2057,7 @@ mod tests {
cwd: None,
title: Some("Error thread".into()),
updated_at: Some(Utc::now()),
created_at: Some(Utc::now()),
meta: None,
},
icon: IconName::ZedAgent,
@ -2068,6 +2075,7 @@ mod tests {
cwd: None,
title: Some("Waiting thread".into()),
updated_at: Some(Utc::now()),
created_at: Some(Utc::now()),
meta: None,
},
icon: IconName::ZedAgent,
@ -2085,6 +2093,7 @@ mod tests {
cwd: None,
title: Some("Notified thread".into()),
updated_at: Some(Utc::now()),
created_at: Some(Utc::now()),
meta: None,
},
icon: IconName::ZedAgent,
@ -3456,6 +3465,7 @@ mod tests {
cwd: None,
title: Some("Test".into()),
updated_at: None,
created_at: None,
meta: None,
},
&workspace_a,
@ -3511,6 +3521,7 @@ mod tests {
cwd: None,
title: Some("Thread B".into()),
updated_at: None,
created_at: None,
meta: None,
},
&workspace_b,